2014-01-22 32 views
3

我正在使用SpringFramework 3和Hibernate 4和MySQL 5 jpa。我的測試代碼看起來像......休眠JDBC批量大小不起作用

@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); 
    } 
    } 
} 

我的spring配置

<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" /> 

我的persistence.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> 

當我打電話我的代碼運行,將火災插入查詢1000次,而不是發射50插入查詢。什麼是問題? 請幫我批量插入jpa使用休眠

+0

好心加疊tracce –

+0

對不起......有沒有異常或在此代碼中的任何錯誤。代碼工作正常,但在控制檯上打印1000次插入查詢。 – Mitesh

回答

1

你誤會了「批量大小」。批量大小意味着一次發送「批量大小」數量的查詢,而不是在代碼觸發查詢時發送每個查詢。因此在這種情況下,將會有1000個插入查詢,每個批次中有20個插入查詢發送50次。

+0

我想這樣做[鏈接](http://stackoverflow.com/questions/6687422/hibernate-batch-size-confusion?answertab=votes#tab-top) – Mitesh

4

請注意,如果插入表的主鍵是GenerationType.Identity,Hibernate將在JDBC級別透明地禁用插入批處理。

save()只有一個記錄,然後flush(),所以每個刷新只能處理一個附加的INSERT SQL。這就是爲什麼Hibernate無法幫助您批量插入,因爲只有一個INSERT SQL需要處理。在調用flush()之前,您應該將()保存到一定數量的記錄中,而不是每次調用save()都調用flush()。

批量插入的最佳做法是這樣的:

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(); 

保存並通過批量刷新紀錄批次。在每個批處理結束時,您應該清除持久化上下文以釋放一些內存,以防止每個持久對象放入第一級緩存(JVM的內存)時耗盡內存。您也可以禁用二級緩存以減少不必要的開銷。

請檢查此鏈接http://docs.jboss.org/hibernate/orm/3.5/reference/en/html/batch.html

+0

你的代碼片段工作正常。但我認爲這段代碼是hibernate特定的代碼,我想用jpa不特定於hibernate。這可能是我的jpa提供者是hibernate,eclipselink或openjpa之一。 – Mitesh

+1

http://stackoverflow.com/questions/2773302/jpa-hibernate-bulkbatch-insert請檢查此https://access.redhat.com/site/documentation/en-US/JBoss_Enterprise_Application_Platform/5/html/Performance_Tuning_Guide/sect -Performance_Tuning_Guide-Entity_Beans-Batch_Inserts.html –