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