NC65数据库操作全攻略:前后台查询与增删改实战(附防SQL注入技巧)

NC65数据库操作全攻略:前后台查询与增删改实战(附防SQL注入技巧) NC65数据库操作全攻略前后台查询与增删改实战附防SQL注入技巧在NC65企业级应用开发中数据库操作是最基础也是最重要的技能之一。不同于常规的JDBC或ORM框架NC65平台提供了自己独特的数据库访问机制涵盖了从前台UI层到后台服务层的完整解决方案。本文将深入剖析这些技术细节帮助开发者快速掌握核心要领。1. 前台数据库操作精要前台操作通常指运行在客户端如浏览器的代码逻辑NC65通过IUAPQueryBS服务提供标准化的查询能力。这个设计巧妙地将复杂的SQL执行过程封装成简单的API调用同时支持多种结果处理方式。基础查询示例IUAPQueryBS queryBS NCLocator.getInstance().lookup(IUAPQueryBS.class); String sql SELECT * FROM bd_material WHERE nvl(dr,0)0; ListMapString,Object result queryBS.executeQuery(sql, new MapListProcessor());常用的结果处理器包括MapListProcessor返回ListMap结构适合动态字段场景BeanListProcessor自动映射到VO对象集合ColumnProcessor提取单列数据ArrayListProcessor原始Object[]数组格式提示前台查询应避免大结果集建议通过WHERE条件精确控制数据量对于单据类操作推荐使用封装好的高阶API// 通过主键获取单据AGGVO SalesOrderVO billVO HYPubBO_Client.queryBillVOByPrimaryKey( SalesOrderVO.class, 1001A110000000000ABC );2. 后台数据库操作深度解析后台操作通常指服务端私有方法具有更高的灵活性和性能优势。BaseDAO是核心工具类支持完整的CRUD操作。2.1 查询操作模式对比方法返回类型适用场景示例executeQueryArrayListProcessorListObject[]原始数据查询多表联合查询executeQueryMapProcessorMapString,Object单行记录主键精确查询executeQueryBeanListProcessorList业务对象集合单据列表查询executeQuery自定义Processor任意类型特殊数据处理树形结构构建典型查询示例// 获取单行记录 String sql SELECT * FROM bd_supplier WHERE pk_supplier?; SQLParameter param new SQLParameter(); param.addParam(1001A110000000000XYZ); MapString,Object supplier (MapString,Object)baseDAO.executeQuery( sql, param, new MapProcessor() ); // 获取VO对象集合 String hql FROM MaterialVO WHERE materialType?; ListMaterialVO materials (ListMaterialVO)baseDAO.executeQuery( hql, new SQLParameter(RAW), new BeanListProcessor(MaterialVO.class) );2.2 增删改操作要点更新操作需要特别注意事务管理try { baseDAO.startTransaction(); // 插入操作 String insertSQL INSERT INTO bd_department(pk_dept,dept_code) VALUES(?,?); SQLParameter insertParam new SQLParameter(); insertParam.addParam(UUID.randomUUID().toString()); insertParam.addParam(DEPT_001); baseDAO.executeUpdate(insertSQL, insertParam); // 更新操作 String updateSQL UPDATE bd_department SET dept_name? WHERE pk_dept?; SQLParameter updateParam new SQLParameter(); updateParam.addParam(研发中心); updateParam.addParam(1001A110000000000KKK); baseDAO.executeUpdate(updateSQL, updateParam); baseDAO.commit(); } catch(Exception e) { baseDAO.rollback(); throw e; }3. 前后台通用操作方案对于需要前后台复用的数据库逻辑NC65提供了中间层服务抽象。IBillQueryService是最常用的接口之一// 获取服务实例 IBillQueryService queryService NCLocator.getInstance().lookup(IBillQueryService.class); // 执行分页查询 PageCond page new PageCond(1, 20); String countSQL SELECT COUNT(*) FROM bd_customer; String dataSQL SELECT * FROM bd_customer; SQLParameter param new SQLParameter(); param.addParam(ACTIVE); QueryResult result queryService.queryWithPage( countSQL, dataSQL, param, page, new MapListProcessor() );性能优化建议对于大数据量查询务必使用分页机制频繁访问的数据考虑使用平台缓存复杂查询建议在后台实现4. SQL注入防御实战安全是数据库操作的重中之重NC65提供了多重防护机制4.1 参数化查询标准写法StringBuilder sql new StringBuilder(); sql.append(SELECT * FROM bd_user ); sql.append(WHERE user_code? ); sql.append(AND nvl(dr,0)?); SQLParameter param new SQLParameter(); param.addParam(admin); // 用户输入参数 param.addParam(0); // 系统参数 ListUserVO users (ListUserVO)baseDAO.executeQuery( sql.toString(), param, new BeanListProcessor(UserVO.class) );4.2 动态SQL安全构建对于条件不固定的查询推荐使用安全拼接方式SQLBuilder builder new SQLBuilder(SELECT * FROM bd_warehouse WHERE 11); if(StringUtils.isNotEmpty(warehouseCode)){ builder.append( AND warehouse_code:code); builder.setParameter(code, warehouseCode); } if(StringUtils.isNotEmpty(warehouseType)){ builder.append( AND warehouse_type:type); builder.setParameter(type, warehouseType); } ListWarehouseVO warehouses (ListWarehouseVO)baseDAO.executeQuery( builder.toString(), builder.getParameters(), new BeanListProcessor(WarehouseVO.class) );4.3 输入验证策略白名单校验对编码类字段使用正则验证if(!Pattern.matches([A-Z0-9_]{1,20}, userInput)){ throw new BusinessException(输入格式不符合要求); }类型强制转换数字型参数必须转换try { Integer.parseInt(inputQty); } catch(NumberFormatException e) { // 异常处理 }长度限制防止超长字符串攻击if(inputString.length() 100){ inputString inputString.substring(0,100); }5. 高级技巧与最佳实践5.1 批量操作优化对于大批量数据操作建议使用批处理模式baseDAO.startTransaction(); try { String sql UPDATE bd_inventory SET qtyqty? WHERE pk_material?; BatchSQLParameter batchParam new BatchSQLParameter(); for(InventoryUpdate item : updateList){ SQLParameter param new SQLParameter(); param.addParam(item.getDeltaQty()); param.addParam(item.getMaterialId()); batchParam.addBatch(param); } int[] results baseDAO.executeBatch(sql, batchParam); baseDAO.commit(); } catch(Exception e) { baseDAO.rollback(); throw e; }5.2 存储过程调用NC65平台支持存储过程的标准调用方式String callSQL {call pkg_business.proc_calculate(?,?,?)}; SQLParameter param new SQLParameter(); param.addParam(202301); param.addParam(FACTORY_001); param.addParam(0); // 输出参数注册 Object result baseDAO.executeQuery(callSQL, param, new ColumnProcessor());5.3 元数据查询技巧获取表结构信息String metaSQL SELECT column_name,data_type FROM user_tab_columns WHERE table_name?; ListMapString,Object columns (ListMapString,Object)baseDAO.executeQuery( metaSQL, new SQLParameter(BD_MATERIAL), new MapListProcessor() );在实际项目中我们发现将常用查询封装成工具方法可以显著提升开发效率。比如创建一个DBUtil类包含各种标准的单条查询、列表查询、分页查询等方法。这样既保证了代码规范又减少了重复劳动。