#java #spring_boot #spring_jpa #transaction #flush
Есть проект на стеке spring-boot-2.0.3, spring-data-jpa-2.0.3 и postgresql-9.5.13. Всего три класса: @Entity, @Repository и основной класс. В БД одна таблица с двумя колонками: id и name. Добавляю в эту таблицу 100 000 записей в цикле и замеряю время исполнения запроса, включая или отключая метод flush() класса EntityManager через каждые 100 записей. Ожидаемый результат: при включенном методе flush() время выполнения запроса должно быть значительно меньше, чем при выключенном. Фактический результат: противоположные показания. Вопрос: Что я делаю не так? Структура проекта: application.properties spring.datasource.driver-class-name=org.postgresql.Driver spring.datasource.url=jdbc:postgresql://localhost:5432/twofold spring.datasource.username=postgres spring.datasource.password=postgres User.java package twofold.data; import javax.persistence.*; @Entity @Table(name = "users", schema = "public") public class User { private Long id; private String name; public User() {} public User(String name) { this.name = name; } @Id @SequenceGenerator(name = "users_id_seq", sequenceName = "users_id_seq", allocationSize = 1) @GeneratedValue(strategy = GenerationType.TABLE, generator = "users_id_seq") @Column(name = "id", nullable = false) public Long getId() { return id; } public void setId(Long id) { this.id = id; } @Column(name = "name", nullable = false, length = 50) public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "id: " + id + "; name: " + name + ";"; } } UserRepository.java package twofold.data; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public interface UserRepository extends JpaRepository{ } Application.java package twofold; import twofold.data.User; import twofold.data.UserRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.transaction.annotation.Transactional; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Autowired private UserRepository userRepository; @PersistenceContext private EntityManager entityManager; @Bean public CommandLineRunner addUsers() { return new CommandLineRunner() { @Transactional public void run(String... args) throws Exception { long incoming = System.currentTimeMillis(); for (int i = 1; i <= 100000; i++) { userRepository.save(new User(i + "_name")); if (i % 100 == 0) { entityManager.flush(); entityManager.clear(); } } System.out.println("Time: " + (System.currentTimeMillis()-incoming)); } }; } }
Ответы
Ответ 1
Если в двух словах, то метод flush() производит запись сохраненных данных непосредственно в СУБД. При нормальном исполнении (без flush) у вас данные в БД попадают не сразу, а после того, как завершится транзакция (при настройках по умолчанию). То есть ваш код за эти 100 000 итераций порождает около 1000 походов в БД для сохранения данных, что увеличивает время выполнения метода.
Комментариев нет:
Отправить комментарий