gpt4 book ai didi

spring - 使用 Spring JDBC 的 PreparedStatementCreator 的正确方法是什么?

转载 作者:IT老高 更新时间:2023-10-28 13:50:34 24 4
gpt4 key购买 nike

据我了解,在 Java 中使用 PreparedStatement 是我们可以多次使用它。但是我在使用 Spring JDBC 的 PreparedStatementCreator 时有些困惑。

例如考虑以下代码,

public class SpringTest {

JdbcTemplate jdbcTemplate;
PreparedStatementCreator preparedStatementCreator;
ResultSetExtractor<String> resultSetExtractor;

public SpringTest() throws SQLException {

jdbcTemplate = new JdbcTemplate(OracleUtil.getDataSource());

preparedStatementCreator = new PreparedStatementCreator() {
String query = "select NAME from TABLE1 where ID=?";
public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
return connection.prepareStatement(query);
}
};

resultSetExtractor = new ResultSetExtractor<String>() {
public String extractData(ResultSet resultSet) throws SQLException,
DataAccessException {
if (resultSet.next()) {
return resultSet.getString(1);
}
return null;
}
};
}
public String getNameFromId(int id){
return jdbcTemplate.query(preparedStatementCreator, new Table1Setter(id), resultSetExtractor);
}

private static class Table1Setter implements PreparedStatementSetter{

private int id;
public Table1Setter(int id) {
this.id =id;
}
@Override
public void setValues(PreparedStatement preparedStatement) throws SQLException {
preparedStatement.setInt(1, id);
}
}
public static void main(String[] args) {
try {
SpringTest springTest = new SpringTest();

for(int i=0;i<10;i++){
System.out.println(springTest.getNameFromId(i));
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}

根据这段代码,当我调用 springTest.getNameFromId(int id) 方法时,它从给定的 id 返回名称,这里我使用 PreparedStatementCreator 创建 PreparedStatement 并使用 PreparedStatementSetter 设置输入参数,我从 ResultSetExtractor 得到结果。但是性能很慢。

在调试并查看 PreparedStatementCreator 和 JdbcTemplate 内部发生的情况后,我知道 PreparedStatementCreator 每次都会创建新的 PreparedStatement...!!!

每当我调用方法 jdbcTemplate.query(preparedStatementCreator,preparedStatementSetter,resultSetExtractor) 时,它都会创建新的 PreparedStatement,这会降低性能。

这是使用 PreparedStatementCreator 的正确方法吗?因为在这段代码中我无法重用 PreparedStatement。如果这是使用 PreparedStatementCreator 的正确方法,那么如何从 PreparedStatement 的可重用性中获益?

最佳答案

Prepared Statements 通常由底层连接池缓存,因此您不必担心每次都创建一个新的。

所以我认为你的实际用法是正确的。

JdbcTemplate 在执行后关闭语句,所以如果你真的想重用同一个准备好的语句,你可以代理语句并在语句创建器中拦截 close 方法

例如(未测试,仅作为示例):

public abstract class ReusablePreparedStatementCreator implements PreparedStatementCreator {

private PreparedStatement statement;

public PreparedStatement createPreparedStatement(Connection conn) throws SQLException {
if (statement != null)
return statement;

PreparedStatement ps = doPreparedStatement(conn);

ProxyFactory pf = new ProxyFactory(ps);
MethodInterceptor closeMethodInterceptor = new MethodInterceptor() {

@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
return null; // don't close statement
}
};

NameMatchMethodPointcutAdvisor closeAdvisor = new NameMatchMethodPointcutAdvisor();
closeAdvisor.setMappedName("close");
closeAdvisor.setAdvice(closeMethodInterceptor);
pf.addAdvisor(closeAdvisor);

statement = (PreparedStatement) pf.getProxy();

return statement;
}

public abstract PreparedStatement doPreparedStatement(Connection conn) throws SQLException;

public void close() {
try {
PreparedStatement ps = (PreparedStatement) ((Advised) statement).getTargetSource().getTarget();
ps.close();
} catch (Exception e) {
// handle exception
}
}

}

关于spring - 使用 Spring JDBC 的 PreparedStatementCreator 的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15113610/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com