在PreparedStatement中使用命名参数
2007-04-09 12:42
295 查看
PreparedStatement中参数都是使用下标传值,如:
PreparedStatement p = con.prepareStatement("select * from people where
(first_name = ? or last_name = ?) and address = ?");
p.setString(1, name);
p.setString(2, name);
p.setString(3, address);
但是如果查询语句复杂,或者修改了sql,要跟踪每个参数的下标将变得非常麻烦并且容易出错,如果使用名称来命名参数就可以解决这个问题,如:
PreparedStatement p = con.prepareStatement("select * from people where
(first_name =:name or last_name =:name) and address =:address");
p.setString("name", name);
p.setString("address", address);
实现:
public class NamedParameterStatement {
private final PreparedStatement statement;
private final Map indexMap;
public NamedParameterStatement(Connection connection, String query)
throws SQLException {
indexMap = new HashMap();
String parsedQuery = parse(query, indexMap);
statement = connection.prepareStatement(parsedQuery);
}
static final String parse(String query, Map paramMap) {
int length = query.length();
StringBuffer parsedQuery = new StringBuffer(length);
boolean inSingleQuote = false;
boolean inDoubleQuote = false;
int index = 1;
for (int i = 0; i < length; i++) {
char c = query.charAt(i);
if (inSingleQuote) {
if (c == '/'') {
inSingleQuote = false;
}
} else if (inDoubleQuote) {
if (c == '"') {
inDoubleQuote = false;
}
} else {
if (c == '/'') {
inSingleQuote = true;
} else if (c == '"') {
inDoubleQuote = true;
} else if (c == ':' && i + 1 < length
&& Character.isJavaIdentifierStart(query.charAt(i + 1))) {
int j = i + 2;
while (j < length
&& Character.isJavaIdentifierPart(query.charAt(j))) {
j++;
}
String name = query.substring(i + 1, j);
c = '?';
i += name.length();
List indexList = (List) paramMap.get(name);
if (indexList == null) {
indexList = new LinkedList();
paramMap.put(name, indexList);
}
indexList.add(new Integer(index));
index++;
}
}
parsedQuery.append(c);
}
for (Iterator itr = paramMap.entrySet().iterator(); itr.hasNext();) {
Map.Entry entry = (Map.Entry) itr.next();
List list = (List) entry.getValue();
int[] indexes = new int[list.size()];
int i = 0;
for (Iterator itr2 = list.iterator(); itr2.hasNext();) {
Integer x = (Integer) itr2.next();
indexes[i++] = x.intValue();
}
entry.setValue(indexes);
}
return parsedQuery.toString();
}
private int[] getIndexes(String name) {
int[] indexes = (int[]) indexMap.get(name);
if (indexes == null) {
throw new IllegalArgumentException("Parameter not found: " + name);
}
return indexes;
}
public void setObject(String name, Object value) throws SQLException {
int[] indexes = getIndexes(name);
for (int i = 0; i < indexes.length; i++) {
statement.setObject(indexes[i], value);
}
}
public void setString(String name, String value) throws SQLException {
int[] indexes = getIndexes(name);
for (int i = 0; i < indexes.length; i++) {
statement.setString(indexes[i], value);
}
}
public void setInt(String name, int value) throws SQLException {
int[] indexes = getIndexes(name);
for (int i = 0; i < indexes.length; i++) {
statement.setInt(indexes[i], value);
}
}
public void setLong(String name, long value) throws SQLException {
int[] indexes = getIndexes(name);
for (int i = 0; i < indexes.length; i++) {
statement.setLong(indexes[i], value);
}
}
public void setTimestamp(String name, Timestamp value) throws SQLException {
int[] indexes = getIndexes(name);
for (int i = 0; i < indexes.length; i++) {
statement.setTimestamp(indexes[i], value);
}
}
public PreparedStatement getStatement() {
return statement;
}
public boolean execute() throws SQLException {
return statement.execute();
}
public ResultSet executeQuery() throws SQLException {
return statement.executeQuery();
}
public int executeUpdate() throws SQLException {
return statement.executeUpdate();
}
public void close() throws SQLException {
statement.close();
}
public void addBatch() throws SQLException {
statement.addBatch();
}
public int[] executeBatch() throws SQLException {
return statement.executeBatch();
}
}
使用时:
String query = "select * from people where (first_name = :name or last_name
= :name) and address = :address");
NamedParameterStatement p = new NamedParameterStatement(con, query);
p.setString("name", name);
p.setString("address", address);
参考:http://www.javaworld.com/javaworld/jw-04-2007/jw-04-jdbc.html?fsrc=rss-index
PreparedStatement p = con.prepareStatement("select * from people where
(first_name = ? or last_name = ?) and address = ?");
p.setString(1, name);
p.setString(2, name);
p.setString(3, address);
但是如果查询语句复杂,或者修改了sql,要跟踪每个参数的下标将变得非常麻烦并且容易出错,如果使用名称来命名参数就可以解决这个问题,如:
PreparedStatement p = con.prepareStatement("select * from people where
(first_name =:name or last_name =:name) and address =:address");
p.setString("name", name);
p.setString("address", address);
实现:
public class NamedParameterStatement {
private final PreparedStatement statement;
private final Map indexMap;
public NamedParameterStatement(Connection connection, String query)
throws SQLException {
indexMap = new HashMap();
String parsedQuery = parse(query, indexMap);
statement = connection.prepareStatement(parsedQuery);
}
static final String parse(String query, Map paramMap) {
int length = query.length();
StringBuffer parsedQuery = new StringBuffer(length);
boolean inSingleQuote = false;
boolean inDoubleQuote = false;
int index = 1;
for (int i = 0; i < length; i++) {
char c = query.charAt(i);
if (inSingleQuote) {
if (c == '/'') {
inSingleQuote = false;
}
} else if (inDoubleQuote) {
if (c == '"') {
inDoubleQuote = false;
}
} else {
if (c == '/'') {
inSingleQuote = true;
} else if (c == '"') {
inDoubleQuote = true;
} else if (c == ':' && i + 1 < length
&& Character.isJavaIdentifierStart(query.charAt(i + 1))) {
int j = i + 2;
while (j < length
&& Character.isJavaIdentifierPart(query.charAt(j))) {
j++;
}
String name = query.substring(i + 1, j);
c = '?';
i += name.length();
List indexList = (List) paramMap.get(name);
if (indexList == null) {
indexList = new LinkedList();
paramMap.put(name, indexList);
}
indexList.add(new Integer(index));
index++;
}
}
parsedQuery.append(c);
}
for (Iterator itr = paramMap.entrySet().iterator(); itr.hasNext();) {
Map.Entry entry = (Map.Entry) itr.next();
List list = (List) entry.getValue();
int[] indexes = new int[list.size()];
int i = 0;
for (Iterator itr2 = list.iterator(); itr2.hasNext();) {
Integer x = (Integer) itr2.next();
indexes[i++] = x.intValue();
}
entry.setValue(indexes);
}
return parsedQuery.toString();
}
private int[] getIndexes(String name) {
int[] indexes = (int[]) indexMap.get(name);
if (indexes == null) {
throw new IllegalArgumentException("Parameter not found: " + name);
}
return indexes;
}
public void setObject(String name, Object value) throws SQLException {
int[] indexes = getIndexes(name);
for (int i = 0; i < indexes.length; i++) {
statement.setObject(indexes[i], value);
}
}
public void setString(String name, String value) throws SQLException {
int[] indexes = getIndexes(name);
for (int i = 0; i < indexes.length; i++) {
statement.setString(indexes[i], value);
}
}
public void setInt(String name, int value) throws SQLException {
int[] indexes = getIndexes(name);
for (int i = 0; i < indexes.length; i++) {
statement.setInt(indexes[i], value);
}
}
public void setLong(String name, long value) throws SQLException {
int[] indexes = getIndexes(name);
for (int i = 0; i < indexes.length; i++) {
statement.setLong(indexes[i], value);
}
}
public void setTimestamp(String name, Timestamp value) throws SQLException {
int[] indexes = getIndexes(name);
for (int i = 0; i < indexes.length; i++) {
statement.setTimestamp(indexes[i], value);
}
}
public PreparedStatement getStatement() {
return statement;
}
public boolean execute() throws SQLException {
return statement.execute();
}
public ResultSet executeQuery() throws SQLException {
return statement.executeQuery();
}
public int executeUpdate() throws SQLException {
return statement.executeUpdate();
}
public void close() throws SQLException {
statement.close();
}
public void addBatch() throws SQLException {
statement.addBatch();
}
public int[] executeBatch() throws SQLException {
return statement.executeBatch();
}
}
使用时:
String query = "select * from people where (first_name = :name or last_name
= :name) and address = :address");
NamedParameterStatement p = new NamedParameterStatement(con, query);
p.setString("name", name);
p.setString("address", address);
参考:http://www.javaworld.com/javaworld/jw-04-2007/jw-04-jdbc.html?fsrc=rss-index
相关文章推荐
- webapi中的Route的标签的命名参数name的使用
- setter命名重复 导致mybatis 使用实体类当参数时 会出错
- C#命名参数的使用
- VSTS有Bug,分析数据库的维度和维度属性使用中文命名时候,作为报表参数会出错。虽然有解决办法但是头大。
- 关于hibernate混合使用占位符和命名参数
- 使用ObjectDataSource注意DeleteMethod、UpdateMethod、Insert等方法中参数的命名约定
- c#中的可选参数和命名参数的使用
- 属性参数 - 使用命名过的参数时的常见错误
- 关于JDBC使用命名参数(named parameters)进行存储过程调用的问题
- 对参数使用某种表示输入,修改,输出的命名规则
- 【JPQL】—查询参数、命名查询和使用构造器查询
- Hibernate中日期对比应该使用命名参数绑定
- C#中可选参数和命名参数的定义及使用
- 在 ASP.NET Web API 中,使用 命名空间(namespace) 来作为路由的参数
- 命名参数和可选参数在.NET中的使用
- Yii: URL管理规则中命名参数使用注意点
- 命名参数,防止sql注入,使用named parameter
- 使用规范的url参数命名,降低被攻击的危险,提升应用程序性能
- [Scala函数特性系列]——使用命名参数
- 使用命名参数处理 CallableStatement