Использование подготовленных операторов с JDBCTemplate


Я использую шаблон JDBC и хочу читать из базы данных, используя подготовленные инструкции. Я перебираю много строк в a .csv-файл, и на каждой строке я выполняю несколько запросов SQL select с соответствующими значениями.

Я хочу ускорить чтение из базы данных, но я не знаю, как заставить шаблон JDBC работать с подготовленными инструкциями.

Существует PreparedStatementCreator и PreparedStatementSetter. Как и в этом примере оба они создаются с анонимными внутренними классами. Но внутри класса PreparedStatementSetter у меня нет доступа к значениям, которые я хочу задать в подготовленном операторе.

Поскольку я повторяю через a .csv-файл, я не могу жестко закодировать их в виде строки, потому что я их не знаю. Я также не могу передать их в PreparedStatementSetter, потому что нет аргументов для конструктора. И ставить мои ценности на окончательный уровень тоже было бы глупо.

Я привык к созданию подготовленных утверждения довольно просты. Что-то вроде

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

Как в этом учебнике Java.

5 23

5 ответов:

По умолчанию JDBCTemplate делает свой собственный PreparedStatement внутренне, если вы просто используете форму .update(String sql, Object ... args). Spring и ваша база данных будут управлять скомпилированным запросом для вас, поэтому вам не нужно беспокоиться об открытии, закрытии, защите ресурсов и т. д. Одна из спасительных Благодатей весны. ссылка на документацию Spring 2.5 по этому вопросу.Надеюсь, это прояснит ситуацию. Кроме того, кэширование операторов может выполняться на уровне JDBC, как и в случае , по крайней мере, некоторых драйверов JDBC Oracle. Это пройдет гораздо более подробно, чем я могу со знанием дела.

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);
    }
}

Попробуйте следующее:

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;
    }
};

Я бы разложил подготовленную обработку операторов по крайней мере на один метод. В этом случае, поскольку результатов нет, это довольно просто (и если предположить, что соединение является переменной экземпляра, которая не изменяется):

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-файла, передайте их как строки. Там также нет блокировки; гораздо лучше, чтобы отдельные соединения использовались из одной нити вместо этого.

Теперь я попробовал оператор select с помощью PreparedStatement, но оказалось, что это не быстрее, чем шаблон Jdbc. Возможно, как предположил мезмо, он автоматически создает подготовленные заявления.

В любом случае, причина, по которой мой sql SELECTбыл таким медленным, была другой. В предложении WHERE я всегда использовал оператор LIKE, когда все, что я хотел сделать, это найти точное соответствие. Как я выяснил, LIKE ищет шаблон и поэтому довольно медленно.

Я использую оператор = теперь и это намного быстрее.