我正在尝试使用hibernate在JPA 2.1中实现批量插入。当我运行我的单元测试以插入20000条记录时,有时我的批量插入运行26秒,有时为11,而正常插入可以运行7秒到34秒。我正在使用以下技术人员:
我使用org.hibernate.ejb.HibernatePersistence作为提供者。是否有可能以这种方式实现批量插入。我应该采取其他方法吗?我的代码如下
persistance.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd" version="2.1">
<persistence-unit name="batchSettingsUnitTest" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.repo.MasterDE</class>
<class>com.repo.ChildDE</class>
<properties>
<property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver" />
<property name="hibernate.connection.url" value="jdbc:hsqldb:mem:BatchDB" />
<property name="hibernate.connection.username" value="sa" />
<property name="hibernate.connection.password" value="" />
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" />
<property name="hibernate.batch.jdbc_size" value="10" />
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
<property name="hibernate.connection.pool_size" value="1" />
<property name="hibernate.current_session_context_class" value="thread" />
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.internal.NoCacheProvider" />
<property name="hibernate.order_inserts" value = "true" />
</properties>
</persistence-unit>
<persistence-unit name="withoutBatchSettingsUnitTest" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.repo.MasterDE</class>
<class>com.repo.ChildDE</class>
<properties>
<property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver" />
<property name="hibernate.connection.url" value="jdbc:hsqldb:mem:NoBatchDB" />
<property name="hibernate.connection.username" value="sa" />
<property name="hibernate.connection.password" value="" />
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" />
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
</properties>
</persistence-unit>
</persistence>
我的测试是:
public class TestHsqMemBatchProcessing {
private int numberOfRows = 20000;
private EntityManagerGenerator entityManagerGenerator = new EntityManagerGenerator();
@Test
public void testBatchInsert() {
int previousmastersCount = 0;
int previouschildsCount = 0;
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("batchSettingsUnitTest");
EntityManager entityManager = EntityManagerFactory.createEntityManager();
entityManager.setFlushMode(FlushModeType.COMMIT);
EntityTransaction batchEntityTransaction = entityManager.getTransaction();
List<masterDE> masters = populateData(3001, 301,numberOfRows, "B");
batchEntityTransaction.begin();
try {
for (int i = 0; i < masters.size(); i++) {
entityManager.persist(masters.get(i));
if (i % 10 == 0) {
entityManager.flush();
entityManager.clear();
}
}
batchEntityTransaction.commit();
Query mastersQuery = entityManager
.createNamedQuery("masterDE.findAll");
Query childsQuery = entityManager
.createNamedQuery("childDE.findAll");
List<masterDE> mastersRetreive = mastersQuery
.getResultList();
List<childDE> childsRetreive = childsQuery
.getResultList();
assertEquals(
"Number of MasterDE insert into Hsql must match ",
numberOfRows + previousmastersCount,
mastersRetreive.size());
assertEquals(
"Number of ChildDE insert into Hsql must match ",
numberOfRows + previouschildsCount,
childsRetreive.size());
} catch (Exception cve) {
batchEntityTransaction.rollback();
throw cve;
} finally {
if (entityManager.isOpen())
entityManager.close();
}
}
@Test
public void testWithoutBatchInsert() {
int previousmastersCount = 0;
int previouschildsCount = 0;
EntityManager entityManager = entityManagerGenerator
.create("withoutBatchSettingsUnitTest");
EntityTransaction batchEntityTransaction = entityManager
.getTransaction();
List<masterDE> masters = populateData(6001, 601,
numberOfRows, "W");
batchEntityTransaction.begin();
for (int i = 0; i < masters.size(); i++) {
entityManager.persist(masters.get(i));
}
batchEntityTransaction.commit();
Query mastersQuery = entityManager
.createNamedQuery("masterDE.findAll");
Query childsQuery = entityManager
.createNamedQuery("childDE.findAll");
List<masterDE> mastersRetreive = mastersQuery
.getResultList();
List<childDE> childsRetreive = childsQuery
.getResultList();
assertEquals("Number of MasterDE insert into Hsql must match ",
numberOfRows + previousmastersCount,
mastersRetreive.size());
assertEquals("Number of ChildDE insert into Hsql must match ",
numberOfRows + previouschildsCount,
childsRetreive.size());
if (entityManager.isOpen())
entityManager.close();
}
private List<masterDE> populateData(int masterTrackingId,
int childTrackingId, int count, String prefix) {
//do stuff to generate data
return data;
}
}