Пружина JdbcTemplate пакетная вставка, пакетное обновление, а также @Транзакционный примеры.
Используемые технологии:
- Пружинный ботинок 2.1.2. ВЫПУСК
- Весенний ВЫПУСК JDBC 5.1.4.
- Мавен 3
- Java 8
1. Пакетная вставка
1.1 Вставьте пакет вставок SQL вместе.
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
public int[] batchInsert(List books) {
return this.jdbcTemplate.batchUpdate(
"insert into books (name, price) values(?,?)",
new BatchPreparedStatementSetter() {
public void setValues(PreparedStatement ps, int i) throws SQLException {
ps.setString(1, books.get(i).getName());
ps.setBigDecimal(2, books.get(i).getPrice());
}
public int getBatchSize() {
return books.size();
}
});
}
1.2 Если партия слишком велика, мы можем разделить ее на меньший размер партии.
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.ParameterizedPreparedStatementSetter;
public int[][] batchInsert(List books, int batchSize) {
int[][] updateCounts = jdbcTemplate.batchUpdate(
"insert into books (name, price) values(?,?)",
books,
batchSize,
new ParameterizedPreparedStatementSetter() {
public void setValues(PreparedStatement ps, Book argument)
throws SQLException {
ps.setString(1, argument.getName());
ps.setBigDecimal(2, argument.getPrice());
}
});
return updateCounts;
}
2. Пакетное обновление
2.1 То же самое для инструкции обновления SQL.
import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.BatchPreparedStatementSetter; public int[] batchUpdate(Listbooks) { return this.jdbcTemplate.batchUpdate( "update books set price = ? where id = ?", new BatchPreparedStatementSetter() { public void setValues(PreparedStatement ps, int i) throws SQLException { ps.setBigDecimal(1, books.get(i).getPrice()); ps.setLong(2, books.get(i).getId()); } public int getBatchSize() { return books.size(); } }); }
2.2 Обновление по размеру пакета.
import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.ParameterizedPreparedStatementSetter; public int[][] batchUpdate(Listbooks, int batchSize) { int[][] updateCounts = jdbcTemplate.batchUpdate( "update books set price = ? where id = ?", books, batchSize, new ParameterizedPreparedStatementSetter () { public void setValues(PreparedStatement ps, Book argument) throws SQLException { ps.setBigDecimal(1, argument.getPrice()); ps.setLong(2, argument.getId()); } }); return updateCounts; }
3. Бежать
3.1 Создайте таблицу для тестирования пакетной вставки и обновления.
startBookBatchUpdateApp(1000);
void startBookBatchUpdateApp(int size) {
jdbcTemplate.execute("CREATE TABLE books(" +
"id SERIAL, name VARCHAR(255), price NUMERIC(15, 2))");
List books = new ArrayList();
for (int count = 0; count < size; count++) {
books.add(new Book(NameGenerator.randomName(20), new BigDecimal(1.99)));
}
// batch insert
bookRepository.batchInsert(books);
List bookFromDatabase = bookRepository.findAll();
// count
log.info("Total books: {}", bookFromDatabase.size());
// random
log.info("{}", bookRepository.findById(2L).orElseThrow(IllegalArgumentException::new));
log.info("{}", bookRepository.findById(500L).orElseThrow(IllegalArgumentException::new));
// update all books to 9.99
bookFromDatabase.forEach(x -> x.setPrice(new BigDecimal(9.99)));
// batch update
bookRepository.batchUpdate(bookFromDatabase);
List updatedList = bookRepository.findAll();
// count
log.info("Total books: {}", updatedList.size());
// random
log.info("{}", bookRepository.findById(2L).orElseThrow(IllegalArgumentException::new));
log.info("{}", bookRepository.findById(500L).orElseThrow(IllegalArgumentException::new));
}
Выход
Total books: 1000
Book{id=2, name='FcRzgpauFtwfWibpzWog', price=1.99}
Book{id=500, name='htDvtGmksjfGmXGKOCaR', price=1.99}
Total books: 1000
Book{id=2, name='FcRzgpauFtwfWibpzWog', price=9.99}
Book{id=500, name='htDvtGmksjfGmXGKOCaR', price=9.99}
4. @Транзакционный
4.1 С @Транзакционный , любой сбой приводит к откату всей операции, ни одна из книг не будет добавлена.
@Transactional
public int[][] batchInsert(List books, int batchSize) {
int[][] updateCounts = jdbcTemplate.batchUpdate(
"insert into books (name, price) values(?,?)",
books,
batchSize,
new ParameterizedPreparedStatementSetter() {
public void setValues(PreparedStatement ps, Book argument) throws SQLException {
ps.setString(1, argument.getName());
ps.setBigDecimal(2, argument.getPrice());
}
});
return updateCounts;
}
4.2 Попробуйте пакетно вставить 1000 книг, #500 содержит ошибку, и весь пакет будет откатан, ни одна книга не будет вставлена.
startBookBatchUpdateRollBack(1000);
void startBookBatchUpdateRollBack(int size) {
jdbcTemplate.execute("CREATE TABLE books(" +
"id SERIAL, name VARCHAR(255), price NUMERIC(15, 2))");
List books = new ArrayList();
for (int count = 0; count < size; count++) {
if (count == 500) {
// Create an invalid data for id 500, test rollback
// Name max 255, this book has length of 300
books.add(new Book(NameGenerator.randomName(300), new BigDecimal(1.99)));
continue;
}
books.add(new Book(NameGenerator.randomName(20), new BigDecimal(1.99)));
}
try {
// with @Transactional, any error, entire batch will be rolled back
bookRepository.batchInsert(books, 100);
} catch (Exception e) {
System.err.println(e.getMessage());
}
List bookFromDatabase = bookRepository.findAll();
// count = 0 , id 500 error, roll back all
log.info("Total books: {}", bookFromDatabase.size());
}
Выход
PreparedStatementCallback; SQL [insert into books (name, price) values(?,?)]; Value too long for column "NAME VARCHAR(255)" Total books: 0
Скачать Исходный Код
Рекомендации
- JDBC Пакетные операции JavaDocs
- Весенние документы JDBC
- Примеры JDBC с пружинной загрузкой _
- Учебное пособие по Java JDBC
Оригинал: “https://mkyong.com/spring/spring-jdbctemplate-batchupdate-example/”