1. 程式人生 > >在PreparedStatement中使用命名引數

在PreparedStatement中使用命名引數

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