【问题标题】:How to avoid JPA persist directly insert into database?如何避免 JPA 持久化直接插入数据库?
【发布时间】:2021-09-03 03:40:09
【问题描述】:

这是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


    【解决方案1】:

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

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

    【讨论】:

    • 我觉得这些东西很棘手。如果实体 ID 依赖于数据库(mysql),那么我们可能无法使用批处理持久化。我所有的实体都是新的Object,它们的ID依赖于mysql,因为它们是auto_increment。
    【解决方案2】:

    你应该为休眠启用批处理

    spring.jpa.properties.hibernate.order_inserts=true
    spring.jpa.properties.hibernate.order_updates=true
    spring.jpa.properties.hibernate.jdbc.batch_size=20
    

    并使用

    reWriteBatchedInserts&reWriteBatchedStatements=true

    你的连接字符串结束

    【讨论】:

      猜你喜欢
      • 2018-08-02
      • 1970-01-01
      • 2011-05-29
      • 2019-10-23
      • 1970-01-01
      • 2015-07-19
      • 1970-01-01
      • 1970-01-01
      • 2016-03-22
      相关资源
      最近更新 更多