我想为many reasons使用预先准备好的陈述。 但是,我想创建一个如下所示的方法:
/* This opens a connection, executes the query, and closes the connection */
public static void executeNonQuery(String queryString);
换句话说,我希望我的应用程序逻辑只需要制定查询和输入参数,而不是处理连接和输入。声明。但是,PreparedStatements是从连接对象创建的,因此我当前不得不使用String.format()来准备查询字符串 - 这很丑陋且危险。
有没有办法在不使用String.format()的情况下做我想做的事?
答案 0 :(得分:14)
为什么我需要连接来创建PreparedStatements?
因为这些陈述是在大多数RDBMS
的基础上按连接准备的。
准备好的声明实际上是缓存的执行计划,不会考虑您的权限,编码,整理设置等。
所有这些都是在查询解析期间完成的。
有没有办法在不使用
的情况下做我想做的事情String.format()
在这里看不出为什么需要String.format()
。
您可以将查询实现为类,创建连接并在类构造函数中准备查询,然后在方法中执行它。
参数化查询通常如下所示:
SELECT *
FROM table
WHERE col1 = ?
AND col2 = ?
,其中绑定参数将在查询执行期间替换?
。
如果您想要static
方法:
static
连接句柄。static
创建准备好的查询的key
哈希表,并将准备好的查询的句柄创建为value
。答案 1 :(得分:1)
为什么不让您的“应用程序”逻辑使用您创建的可以呈现这种接口方法的数据层?
然后,您的数据层可以在executeNonQuery
方法中处理创建连接,准备语句等。
我认为如果你试图将查询/语句中的参数自己合并到一个String中,那么你就是在自己的脚下拍摄,实际上并没有使用PreparedStatements的参数功能。不知道你为什么要这样做。
您可能还希望使用一个API,例如Spring,它有一系列JdbcTemplate
类,可以抽象出远离您的所有连接处理,但仍允许您使用Map
。
答案 2 :(得分:0)
通过让我调用QueryRunner的类来抽象出所有JDBC的东西,该类具有一个带有sql的execute方法,一个表示参数的对象List,以及一个将处理ResultSet的对象。如果使用JDBC中的setObject方法设置参数,它将根据底层对象确定要使用的相应数据库类型。这是我的一部分代码。我有另一个方法来包装这个并获得连接。
public void executeNoCommit(Connection conn,
String sql,
List params,
ResultSetProcessor processor) throws SQLException {
PreparedStatement stmt = null;
ResultSet rs = null;
int updateCount = 0;
Iterator it;
int paramIndex = 1;
boolean query;
try {
stmt = conn.prepareStatement(sql);
if (params != null) {
it = params.iterator();
while (it.hasNext()) {
stmt.setObject(paramIndex, it.next());
paramIndex++;
}
}
query = stmt.execute();
if (query) {
rs = stmt.getResultSet();
}
else {
updateCount = stmt.getUpdateCount();
}
processor.process(rs, updateCount);
}
finally {
if (rs != null) {
try {
rs.close();
}
catch (SQLException e) {
log.error(e);
}
}
if (stmt != null) {
try {
stmt.close();
}
catch (SQLException e) {
log.error(e);
}
}
}
}
答案 3 :(得分:0)
你可能想要像Apache Commons库中的DbUtils包这样的东西:[http://commons.apache.org/dbutils/index.html][1]
QueryRunner类允许您执行sql语句,而无需手动创建PreparedStatements,甚至可以打开连接。从示例页面:
QueryRunner run = new QueryRunner( dataSource );
try
{
// Create an object array to hold the values to insert
Object[] insertParams = {"John Doe", new Double( 1.82 )};
// Execute the SQL update statement and return the number of
// inserts that were made
int inserts = run.update( "INSERT INTO Person (name,height) VALUES (?,?)",
insertParams );
// Now it's time to rise to the occation...
Object[] updateParams = {new Double( 2.05 ), "John Doe"};
int updates = run.update( "UPDATE Person SET height=? WHERE name=?",
updateParams );
}
catch(SQLException sqle) {
// Handle it
}
因此它基本上是透明地处理预准备语句的创建,而您真正需要知道的唯一事情是DataSource。这也适用于非更新/插入语句,即普通选择查询,并且创建ResultSetHandlers的功能使您能够将ResultSet转换为类似完全准备好的bean或带有键的Map。作为列名,值是实际的行值。当您无法实现整个ORM解决方案时非常有用。