Java 为什么我需要一个连接来创建PreparedStatements?
我想使用事先准备好的声明,例如。 但是,我想创建一个如下所示的方法:Java 为什么我需要一个连接来创建PreparedStatements?,java,sql,jdbc,prepared-statement,Java,Sql,Jdbc,Prepared Statement,我想使用事先准备好的声明,例如。 但是,我想创建一个如下所示的方法: /* This opens a connection, executes the query, and closes the connection */ public static void executeNonQuery(String queryString); SELECT * FROM table WHERE col1 = ? AND col2 = ? 换句话说,我希望我的应用程序逻辑只需
/* This opens a connection, executes the query, and closes the connection */
public static void executeNonQuery(String queryString);
SELECT *
FROM table
WHERE col1 = ?
AND col2 = ?
换句话说,我希望我的应用程序逻辑只需要制定查询和输入参数,而不需要处理连接和语句。但是,PreparedStatements是从连接对象创建的,因此我目前被迫使用string.format()-来准备查询字符串
有没有一种方法可以不使用String.format()完成我想要的操作
为什么我需要一个连接来创建PreparedStatements
因为在大多数RDBMS
中,这些语句是基于每个连接准备的
准备好的语句实际上是缓存的执行计划,它不考虑您的权限、编码、排序规则设置等
所有这些都是在查询解析期间完成的
有没有办法不用String.format()
不明白为什么需要在此处使用String.format()
您可以将查询实现为类,创建连接,在类构造函数中准备查询,然后在方法中执行查询
参数化查询通常如下所示:
/* This opens a connection, executes the query, and closes the connection */
public static void executeNonQuery(String queryString);
SELECT *
FROM table
WHERE col1 = ?
AND col2 = ?
,其中,在查询执行期间,绑定参数将替换为?
如果需要静态方法
:
- 创建一个
连接句柄静态
- 使用参数化查询文本作为
,并将准备好的查询的句柄作为键
,创建准备好的查询的值
哈希表静态
- 无论何时要执行查询,都要找到其句柄(如果找不到,则创建它),并使用来绑定参数并执行查询
executeNonQuery
方法中
我认为,如果您试图自己将查询/语句中的参数合并成一个字符串,那么您就是自食其果,实际上没有使用PreparedStatements的参数功能。不知道你为什么要这样做
您可能还需要考虑使用一个API,比如Spring,它有一系列的
JdbcTemplate
类,这些类可以将所有连接处理抽象出来,但是仍然允许您使用映射中的参数我通过使用一个名为QueryRunner的类来提取所有JDBC内容,该类具有一个接受sql的执行方法、一个表示参数的对象列表和一个将处理结果集的对象。如果使用JDBC中的setObject方法来设置参数,它将根据底层对象找出要使用的适当DB类型。这是我代码的一部分。我有另一个方法,它把这个包起来,得到的是连接
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);
}
}
}
}
在Apache Commons库中,您可能需要类似于DbUtils包的东西:[
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
}
因此,它基本上透明地处理准备语句的创建,您真正需要知道的唯一一件事是数据源。这也适用于非更新/插入语句,即普通的select查询,并且创建ResultSetHandler的功能使您能够将ResultSet转换为类似ful的内容准备得很好的bean,或者是一个映射,其中键是列名,值是实际的行值。对于无法实现整个ORM解决方案的情况非常有用。ExecuteOnQuery方法有一个问题:获取连接。如果每次执行此方法时都创建一个连接,则在一段时间内执行时会出现性能问题d over(创建和关闭连接非常昂贵)。如果将其封装在仅在第一次调用时创建连接的对象上,则会出现问题:何时关闭?可能基于时间?如果使用静态字段进行缓存,则不会收集到该数据。但是,在缓存连接时,请注意并发调用:没有锁定机制(例如syncrhonized),您可以创建许多连接。