让JAVA的JDBC支持命名参数的SQL语句
JAVA 的JDBC连接数据库时,传递参数的方式是通过索引位置实现(根据SQL中?号出现的顺序,例如 SELECT * FROM [table] WHERE [name] ? OR [title]?);这让使用SQL语句变得比较麻烦也不符合使用习惯。为此专门创建了一个类NSQL用于支持命名方式给SQL语句传递参数例如 SELECT * FROM [table] WHERE [name] ?name OR [title]?title。其基本原理是以号为参数标识后跟参数名称在编写SQL语句时候采用命名参数方式然后由NSQL类将其分析后生成JDBC可用的基于号顺序的SQL语句同时记录参数顺序。这样既可实现命名参数的SQL语句。JDBC 命名参数的开源组件https://gitee.com/joyzl/databasehttps://gitcode.com/joyzl/databasehttps://github.com/JoyLinks/database代码如下所示/** * 2017年2月16日 */ package com.kiy.service.data; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * SQL语句抽象提供基于命名参数的SQL语句功能 * * author Simon(ZhangXi) * */ public final class NSQL { // 静态集合缓存使用过的NSQL private static MapString, NSQL caches new ConcurrentHashMapString, NSQL(); private String sql_naming; private String sql_execute; private String[] names; private NSQL() { // 用户不能实例化对象 // 通过get方法获取可用实例 } public boolean hasName() { return names.length 0; } public void setParameter(PreparedStatement ps, String name, Object value) throws SQLException { for (int a 0, b names.length - 1; a b; a, b--) { if (names[a].equals(name)) { ps.setObject(a 1, value); } if (a ! b names[b].equals(name)) { ps.setObject(b 1, value); } } } public void setParameters(PreparedStatement ps, MapString, Object values) throws SQLException { for (int index 0; index names.length; index) { ps.setObject(index 1, values.get(names[index])); } } /** * 获取用于数据库执行的SQL语句 * * return */ public String getSql() { return sql_execute; } /** * 获取用户定义的命名SQL语句 * * return */ public String getNamingSql() { return sql_naming; } /** * 获取对象实例此方法将缓存分析过的SQL语句以提高性能 * * param sql * return */ public static NSQL get(String sql) { NSQL nsql caches.get(sql); if (nsql null) { nsql NSQL.parse(sql); caches.put(sql, nsql); } return nsql; } /** * 分析命名SQL语句获取抽象NSQl实例java(JDBC)提供SQL语句命名参数而是通过?标识参数位置 * 通过此对象可以命名参数方式使用SQL语句命名参数以?开始后跟名称?name。 * 例如SELECT * FROM table WHERE name ?key AND email ?key; * * param sql * return */ public static NSQL parse(String sql) { // SELECT * FROM table WHERE name ?key AND email ?key; // A~Z a~z 01~9 _ if (sql null) throw new NullPointerException(SQL String is null); char c; ListString names new ArrayListString(); StringBuilder sql_builder new StringBuilder(); StringBuilder name_builder new StringBuilder(); for (int index 0; index sql.length(); index) { c sql.charAt(index); sql_builder.append(c); if (? c) { while (index sql.length()) { c sql.charAt(index); if ((c a c z) || (c A c Z) || c _ || (c 0 c 9)) { name_builder.append(c); } else { sql_builder.append(c); break; } } names.add(name_builder.toString()); name_builder.setLength(0); } } NSQL dbsql new NSQL(); dbsql.sql_naming sql; dbsql.sql_execute sql_builder.toString(); dbsql.names names.toArray(dbsql.names new String[names.size()]); return dbsql; } public String toString() { return NAMING: sql_naming \nEXECUTE: sql_execute; } }NSQL类的使用如下所示public boolean CreateUser(User u) { NSQL sql1 NSQL.get(INSERT INTO users (id,name,password,enable,realname,mobile,phone,email,remark,created,updated) VALUES (?id,?name,?password,?enable,?realname,?mobile,?phone,?email,?remark,?created,?created)); Connection connection dbc.get(); try (PreparedStatement s1 connection.prepareStatement(sql1.getSql())) { sql1.setParameter(s1, id, u.getId()); sql1.setParameter(s1, name, u.getName()); sql1.setParameter(s1, password, u.getPassword()); sql1.setParameter(s1, enable, u.getEnable()); sql1.setParameter(s1, realname, u.getRealname()); sql1.setParameter(s1, mobile, u.getMobile()); sql1.setParameter(s1, phone, u.getPhone()); sql1.setParameter(s1, email, u.getEmail()); sql1.setParameter(s1, remark, u.getRemark()); sql1.setParameter(s1, created, u.getCreated()); return s1.executeUpdate() 1; } catch (SQLException ex) { Log.error(ex); return false; } finally { dbc.put(connection); }如此即可通过命名方式使用SQL语句了欢迎大家多多交流。JDBC 命名参数的开源组件https://gitee.com/joyzl/databasehttps://gitcode.com/joyzl/databasehttps://github.com/JoyLinks/database此组件原本属于JOYZL SCADA中访问传统二位数据库的基础模块。但由于传统数据库的灵活性导致其并不适用于庞大的时序数据存取v8 及之后的JOYZL SCADA版本已不在依赖传统数据库全面采用专门的时序数据存取库进而数据吞吐量和存储上限获得极大提升理论上可存储百年以上的时序数据并且可秒级提取任意时段瘦数据。JOYZL SCADA是完全国产化优秀的数据采集与监测控制软件主要应用于工业数据采集监控。