您的位置:首页 > 编程语言 > Java开发

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

2017-04-18 16:57 435 查看
  JAVA 的JDBC连接数据库时,传递参数的方式是通过索引位置实现(根据SQL中?号出现的顺序,例如 SELECT * FROM WHERE [name] =? OR [title]=?);这让使用SQL语句变得比较麻烦也不符合使用习惯。

  为此专门创建了一个类NSQL用于支持命名方式给SQL语句传递参数(例如 SELECT * FROM
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 {

// 静态集合缓存使用过的NSQL
private 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语句了,欢迎大家多多交流。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息