Problem
You want to implement a batch job which writes a large number of records to a database. You decide to use the EntityManager provided by Ivy directly. Since Ivy keeps track of all EntityManagers, that you create, you want to avoid creating a new EntityManager for every record, but instead only use a single EntityManager for the whole operation.
The single EntityManager will hold references to all objects it has seen and will use more and more memory. This will slow down your application and in worst case lead to out-of-memory exceptions.
Solution
If you are re-using an EntityManager for many operations, you should try to clean up as soon as you do not need the managed objects any more. This will typically be the case after a an insert
or update
operation. In general, when you do not need the object any more, you can also remove it from the EntityManager. The easiest solution to do this is to call the EntityManager.clear()
function.
Example
The following example shows how to create millions of records without losing any memory.
IIvyEntityManager ivyEm = Ivy.persistence().get("Test");
// Only create one EntityManager. EntityManagers are hold during the whole request
// by Ivy to report not closed EM at the end of the request!
EntityManager em = ivyEm.createEntityManager();
try {
for (int i = 1; i<=count; i++) {
TestEntity testEntity = new TestEntity();
testEntity.setId(RandomStringUtils.randomAlphanumeric(32));
testEntity.setTest(RandomStringUtils.randomAlphanumeric(10, 255));
EntityTransaction transaction = em.getTransaction();
try {
transaction.begin();
em.merge(testEntity);
transaction.commit();
// testEntity is no longer needed
em.clear();
} catch (Exception e) {
Ivy.log().error("Execption saving object", e);
transaction.rollback();
}
}
}
finally {
em.close();
}