Рубрики
Без рубрики

Пакетное обновление Spring JdbcTemplate() Пример

– Пакетное обновление Spring JdbcTemplate() Пример

Пружина 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(List books) {

        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(List books, 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

Скачать Исходный Код

Рекомендации

Оригинал: “https://mkyong.com/spring/spring-jdbctemplate-batchupdate-example/”