您还可以编写自己的解决方法来完成与 JDBC 中的 NamedParameterStatement 相同的操作:
public class NamedParameterStatement {
// define the parameter format as a colon followed by at least one word letter
private final String PARAMETER_REGEX =":\\w+";
// the parsed sql query string containing question marks,
// not named parameters
private String sql;
// hashtables for parameter mapping
private Hashtable<String, Integer> parameterNameMap;
private Hashtable<Integer, Object> parameterValueMap;
/**
* constructor for named parameter statements
* @param namedParameterSQL the sql query with named parameters
*/
public NamedParameterStatement(String namedParameterSQL) {
// init hashtables
this.parameterNameMap = new Hashtable<String, Integer>();
this.parameterValueMap = new Hashtable<Integer, Object>();
// create a matcher for the named parameter sql query based on
// the pattern specified for the named parameter format
Matcher m = Pattern.compile(
PARAMETER_REGEX,
Pattern.CASE_INSENSITIVE)
.matcher(namedParameterSQL);
int i = 1;
while(m.find()) {
// watch out: this implementation does not check
// for multiple parameters with the same name.
parameterNameMap.put(m.group().replace(":", ""), i++);
}
// replace all named parameters with question marks
this.sql = m.replaceAll("?");
}
/**
* creates a prepared statement for the specified connection,
* based on the parameter mapping
* @param conn the database connection
* @return a prepared statement
* @throws SQLException thrown on error with preparing the statement
* @throws InvalidBindingException thrown on errors with the parameter binding
*/
public PreparedStatement createPreparedStatement(Connection conn)
throws SQLException, InvalidBindingException {
// check if bindings match
if(parameterNameMap.size() == parameterValueMap.size()) {
// create prepared statement
PreparedStatement ps = conn.prepareStatement(this.sql);
// for each parameter binding, set the parameter and its index accordingly
for(Integer i : this.parameterValueMap.keySet()) {
Object value = this.parameterValueMap.get(i);
// map the parameter object types against the different parameter setters
// this mapping is incomplete!!! just a proof of concept.
if(value.getClass() == String.class) {
ps.setString(i, (String) value);
} else if(value.getClass() == Integer.class || value.getClass() == int.class) {
ps.setInt(i, (int) value);
} else if(value.getClass() == Double.class || value.getClass() == double.class) {
ps.setDouble(i, (double) value);
} else if(value.getClass() == Long.class || value.getClass() == long.class) {
ps.setLong(i, (long) value);
}
}
return ps;
}
else throw new InvalidBindingException("Not all parameters were bound.");
}
/**
* returns the converted prepared statement query string
* @return the query string
*/
public String getSQL() {
return this.sql;
}
/**
* binds a parameter value to a parameter name
* @param parameter the parameter name
* @param value the parameter value
*/
public void bindParameter(String parameter, Object value) {
// check if the parameter name existed in the named parameter query string
if(this.parameterNameMap.containsKey(parameter)) {
this.parameterValueMap.put((Integer)this.parameterNameMap.get(parameter), value);
}
else throw new IllegalArgumentException("Parameter '" + parameter + "' does not exist.");
}
}
用法:
NamedParameterStatement nps = new NamedParameterStatement(
"SELECT * FROM table WHERE column1=:param1 AND column2=:param2");
nps.bindParameter("param1", "value1");
nps.bindParameter("param2", 2);
PreparedStatement ps = nps.createPreparedStatement(conn);
ResultSet results = ps.executeQuery();
while(results.next()) {
System.out.println(results.getString("column1"));
}
我知道,这也不理想,但是如果您不想使用 JDBC 或其他框架(Hibernate,...),它就可以解决问题。