使用带有JDBCTemplate的预准备语句

时间:2010-06-07 12:05:04

标签: java spring jdbc prepared-statement jdbctemplate

我正在使用JDBC模板,并希望使用预准备语句从数据库中读取数据。我在.csv文件中迭代多行,并在每一行上执行一些带有相应值的SQL select查询。

我想加快从数据库中读取数据,但我不知道如何让JDBC模板与预处理语句一起使用。

PreparedStatementCreatorPreparedStatementSetter。与在this example中一样,它们都是使用匿名内部类创建的。 但是在PreparedStatementSetter类中,我无法访问我想在预准备语句中设置的值。

因为我正在迭代.csv文件,所以我不能将它们硬编码为String,因为我不知道它们。 我也无法将它们传递给PreparedStatementSetter,因为构造函数没有参数。将我的价值观设定为最终值也是愚蠢的。

我习惯于创建准备好的语句非常简单。像

这样的东西
PreparedStatement updateSales = con.prepareStatement(
    "UPDATE COFFEES SET SALES = ? WHERE COF_NAME LIKE ? ");
updateSales.setInt(1, 75); 
updateSales.setString(2, "Colombian"); 
updateSales.executeUpdate():

,如Java tutorial

5 个答案:

答案 0 :(得分:28)

默认情况下,如果您只使用JDBCTemplate表单,PreparedStatement会在内部自行.update(String sql, Object ... args)。 Spring和您的数据库将为您管理已编译的查询,因此您不必担心打开,关闭,资源保护等等。其中一个保存优点是Spring。 A link to Spring 2.5's documentation on this.希望它能让事情更加清晰。此外,语句缓存可以在JDBC级别完成,如at least some of Oracle's JDBC drivers.的情况 这比我能胜任的细节要多得多。

答案 1 :(得分:18)

class Main {
    public static void main(String args[]) throws Exception {
        ApplicationContext ac = new
          ClassPathXmlApplicationContext("context.xml", Main.class);
        DataSource dataSource = (DataSource) ac.getBean("dataSource");
// DataSource mysqlDataSource = (DataSource) ac.getBean("mysqlDataSource");

        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);

        String prasobhName = 
        jdbcTemplate.query(
           "select first_name from customer where last_name like ?",
            new PreparedStatementSetter() {
              public void setValues(PreparedStatement preparedStatement) throws
                SQLException {
                  preparedStatement.setString(1, "nair%");
              }
            }, 
            new ResultSetExtractor<Long>() {
              public Long extractData(ResultSet resultSet) throws SQLException,
                DataAccessException {
                  if (resultSet.next()) {
                      return resultSet.getLong(1);
                  }
                  return null;
              }
            }
        );
        System.out.println(machaceksName);
    }
}

答案 2 :(得分:10)

尝试以下方法:

PreparedStatementCreator creator = new PreparedStatementCreator() {
    @Override
    public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
        PreparedStatement updateSales = con.prepareStatement(
        "UPDATE COFFEES SET SALES = ? WHERE COF_NAME LIKE ? ");
        updateSales.setInt(1, 75); 
        updateSales.setString(2, "Colombian"); 
        return updateSales;
    }
};

答案 3 :(得分:3)

我将准备好的语句处理分解为至少一个方法。在这种情况下,因为没有结果它相当简单(假设连接是一个不改变的实例变量):

private PreparedStatement updateSales;
public void updateSales(int sales, String cof_name) throws SQLException {
    if (updateSales == null) {
        updateSales = con.prepareStatement(
            "UPDATE COFFEES SET SALES = ? WHERE COF_NAME LIKE ?");
    }
    updateSales.setInt(1, sales);
    updateSales.setString(2, cof_name);
    updateSales.executeUpdate();
}

那时,只需要召唤:

updateSales(75, "Colombian");

与其他东西整合非常简单,是吗?如果你多次调用这个方法,那么更新只会被构造一次,这将使事情变得更快。好吧,假设你不做疯狂的事情,比如在自己的交易中做每次更新......

请注意,类型是固定的。这是因为对于任何特定的查询/更新,它们应该被修复,以便允许数据库有效地完成其工作。如果您只是从CSV文件中提取任意字符串,请将它们作为字符串传递。也没有锁定;更好地保持从单个线程使用单个连接。

答案 4 :(得分:2)

我现在尝试使用PreparedStatement的select语句,但事实证明它并不比Jdbc模板快。也许,正如mezmo建议的那样,它会自动创建预备语句。

无论如何,我的sql SELECT s这么慢的原因是另一个。在WHERE子句中,我总是使用运算符LIKE,当我想要做的就是找到完全匹配。正如我发现LIKE搜索模式一样,因此非常慢。

我现在正在使用运算符=,速度要快得多。