Java Hibernate JDBC 批处理大小不起作用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21275379/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 07:48:42  来源:igfitidea点击:

Hibernate JDBC Batch size is not working

javamysqlspringhibernatejpa

提问by Mitesh

I'm using SpringFramework 3 and Hibernate 4 and MySQL 5 with jpa. My test code looks like...

我正在使用带有 jpa 的 SpringFramework 3、Hibernate 4 和 MySQL 5。我的测试代码看起来像...

@Repository
public class TestRepositoryImpl implements TestRepository {

  @PersistenceContext
  private EntityManager em;

  @Override
  @Transactional
  public void insertBulk() {
     Item it;
     for(int i= 0; i<1000;i++) {
        it = new Item();
        it.setPrice(Math.random()*100);
        em.persist(it);
     }
  }
}

My spring configuration

我的弹簧配置

 <bean id="entityManagerFactory"
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="application" />
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

<tx:annotation-driven transaction-manager="transactionManager" />

my persistence.xml

我的持久性.xml

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">

<persistence-unit name="application" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <class>com.springapp.test.domain.Item</class>
    <class>com.springapp.test.domain.Order</class>
    <exclude-unlisted-classes>true</exclude-unlisted-classes>
    <properties>
        <property name="hibernate.show_sql" value="true" />
        <property name="hibernate.format_sql" value="false" />
        <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" />
        <property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/testdb" />
        <property name="hibernate.connection.username" value="root" />
        <property name="hibernate.connection.password" value="" />
        <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" />
        <property name="hibernate.hbm2ddl.auto" value="update" />
        <property name="hibernate.jdbc.batch_size" value="20" />
    </properties>
</persistence-unit>

</persistence>

When I call run my code it will fires insert query 1000 times instead of firing 50 insert query. What is the issue? Please help me to batch insert in jpa using hibernate

当我调用运行我的代码时,它会触发 1000 次插入查询,而不是触发 50 次插入查询。问题是什么?请帮助我使用休眠在 jpa 中批量插入

回答by RaviH

You have misunderstood "batch size". Batch size means send "batch size" number of queries together in one go instead of sending each query as the code fires the query. Therefore in this case there will be 1000 insert queries, sent 50 times with 20 insert queries in each batch.

您误解了“批量大小”。批量大小意味着一次性发送“批量大小”数量的查询,而不是在代码触发查询时发送每个查询。因此,在这种情况下,将有 1000 个插入查询,发送 50 次,每批发送 20 个插入查询。

回答by Sureshkumar Panneerselvan

Please note that Hibernate would disable insert batching at the JDBC level transparently if the primary key of the inserting table isGenerationType.Identity.

请注意,如果插入表的主键是GenerationType.Identity,Hibernate 将在JDBC 级别透明地禁用插入批处理。

save() only one record and then flush(), so there is only one appending INSERT SQL to be processed for every flush. That's why Hibernate cannot help you to batch inserting as there is only one INSERT SQL to be processed. You should save() up to the certain amount of records before calling flush() instead of calling flush() for every save().

save() 只有一条记录,然后flush(),所以每次刷新只有一个附加的INSERT SQL要处理。这就是 Hibernate 无法帮助您批量插入的原因,因为只有一个 INSERT SQL 需要处理。您应该在调用flush() 之前save() 到一定数量的记录,而不是为每个save() 调用flush()。

The best practise of batch inserting is something like this:

批量插入的最佳实践是这样的:

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
for  ( int i=0; i<888888; i++ ) {
  TableA record = new TableA();
    record.setXXXX();
    session.save(record)
    if ( i % 50 == 0 ) { //50, same as the JDBC batch size
        //flush a batch of inserts and release memory:
        session.flush();
        session.clear();
    }
}
tx.commit();
session.close();

You save and flush the records batch by batch. In the end of each batch you should clear the persistence context to release some memory to prevent memory exhaustion as every persistent object is placed into the first level cache (your JVM's memory). You could also disable the second-level cache to reduce the unnecessary overhead.

您可以逐批保存和刷新记录。在每个批处理结束时,您应该清除持久上下文以释放一些内存,以防止内存耗尽,因为每个持久对象都被放入第一级缓存(您的 JVM 内存)。您还可以禁用二级缓存以减少不必要的开销。

Kindly check this link http://docs.jboss.org/hibernate/orm/3.5/reference/en/html/batch.html

请检查此链接http://docs.jboss.org/hibernate/orm/3.5/reference/en/html/batch.html

回答by Андрей Б

add logger org.hibernate.engine.jdbc.batch.internal.BatchingBatchin level debug. hibernate can generate batches with size 1 or 2 in case of wrong order of inserts. try to use hibernate.order_inserts=true hibernate.order_updates=true

org.hibernate.engine.jdbc.batch.internal.BatchingBatch在级别调试中添加记录器。如果插入顺序错误,hibernate 可以生成大小为 1 或 2 的批次。尝试使用hibernate.order_inserts=true hibernate.order_updates=true