Использование подготовленных операторов с 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 ответов:
По умолчанию
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ищет шаблон и поэтому довольно медленно.Я использую оператор
=теперь и это намного быстрее.