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
Hibernate JDBC Batch size is not working
提问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.BatchingBatch
in 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