让JAVA的JDBC支持命名参数的SQL语句

来源:互联网 发布:网络剧哪里备案 编辑:程序博客网 时间:2024/06/06 04:40

  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语句。

  代码如下所示:

/** * 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 {// 静态集合缓存使用过的NSQLprivate static Map<String, NSQL> caches = new ConcurrentHashMap<String, 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, Map<String, 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;List<String> names = new ArrayList<String>();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语句了,欢迎大家多多交流。

1 0
原创粉丝点击