38

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

我想加快从数据库中读取的速度,但我不知道如何让 JDBC 模板与准备好的语句一起工作。

PreparedStatementCreatorPreparedStatementSetter。在这个例子中,它们都是用匿名内部类创建的。但是在 PreparedStatementSetter 类中,我无法访问我想在准备好的语句中设置的值。

由于我正在遍历 .csv 文件,因此我无法将它们硬编码为字符串,因为我不知道它们。我也无法将它们传递给 PreparedStatementSetter,因为构造函数没有参数。并且将我的值设置为 final 也很愚蠢。

我习惯于创建相当简单的准备好的语句。就像是

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

就像在这个Java 教程中一样。

4

5 回答 5

37

默认情况下,如果您只使用表单,则JDBCTemplate它会在内部执行。Spring 和你的数据库会为你管理编译好的查询,所以你不用担心打开、关闭、资源保护等问题。这是 Spring 的一大优点。指向 Spring 2.5 文档的链接。希望它能让事情更清楚。此外,语句缓存可以在 JDBC 级别完成,至少在一些 Oracle 的 JDBC 驱动程序的情况下。 这将比我能胜任的要详细得多。PreparedStatement.update(String sql, Object ... args)

于 2010-06-07T13:58:22.200 回答
19
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);
    }
}
于 2011-02-11T10:11:57.160 回答
9

尝试以下操作:

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;
    }
};
于 2010-06-07T12:18:56.033 回答
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 文件中提取任意字符串,请将它们作为字符串传递。也没有锁定;最好保持单个连接从单个线程中使用。

于 2010-06-07T12:36:34.050 回答
2

我现在尝试了一个带有 a 的 select 语句PreparedStatement,但结果证明它并不比 Jdbc 模板快。也许,正如 mezmo 所建议的,它会自动创建准备好的语句。

无论如何,我的 sqlSELECT这么慢的原因是另一个原因。在WHERE子句中,我总是使用 operator LIKE,而我只想找到一个完全匹配的。正如我发现的那样LIKE搜索模式,因此速度很慢。

我现在正在使用操作员=,而且速度要快得多。

于 2010-06-08T09:28:27.470 回答