首页 > 解决方案 > 如何避免 JPA 持久化直接插入数据库?

问题描述

这是mysql表。

create table Customer
(
    id          int auto_increment   primary key,
    birth       date        null,
    createdTime time        null,
    updateTime  datetime(6) null
);

这是我的java代码

@Before
public void init() {
    this.entityManagerFactory=Persistence.createEntityManagerFactory("jpaLearn");
    this.entityManager=this.entityManagerFactory.createEntityManager();
    this.entityTransaction=this.entityManager.getTransaction();
    this.entityTransaction.begin();
}
@Test
public void persistentTest() {
    this.entityManager.setFlushMode(FlushModeType.COMMIT); //don't work.
    for (int i = 0; i < 1000; i++) {
        Customer customer = new Customer();
        customer.setBirth(new Date());
        customer.setCreatedTime(new Date());
        customer.setUpdateTime(new Date());
        this.entityManager.persist(customer);
    }
}
@After
public void destroy(){
    this.entityTransaction.commit();
    this.entityManager.close();
    this.entityManagerFactory.close();
}

当我阅读 JPA 的 wikibooks 时,它说“这意味着当您调用持久、合并或删除数据库时,不会执行 DML INSERT、UPDATE、DELETE,直到提交或触发刷新。” 但是在我的代码运行的同时,我阅读了mysql日志,我发现每次持久执行时,mysql都会执行sql。而且我还看了wireShark,每次都会引起对Database的请求。我记得jpa saveAll方法可以批量发送SQL语句到数据库吗?如果我想插入10000条记录,如何提高效率?

标签: jpa

解决方案


我在下面的回答假设您Hibernate用作 jpa 实现。Hibernate 默认不启用批处理。这意味着它将为每个插入/更新操作发送单独的 SQL 语句。

您应该将hibernate.jdbc.batch_size属性设置为大于 0 的数字。最好persistence.xml在您有 jpa 配置的文件中设置此属性,但由于您没有在问题中发布它,所以下面直接在 EntityManagerFactory 上设置。

@Before
public void init() {
    Properties properties = new Properties();
    properties.put("hibernate.jdbc.batch_size", "5");
    this.entityManagerFactory = Persistence.createEntityManagerFactory("jpaLearn", properties);
    this.entityManager = this.entityManagerFactory.createEntityManager();
    this.entityTransaction = this.entityManager.getTransaction();
    this.entityTransaction.begin();
}

然后通过观察您的日志,您应该会看到客户记录以 5 个批次保存在数据库中。

如需进一步阅读,请查看:https ://www.baeldung.com/jpa-hibernate-batch-insert-update


推荐阅读