/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.userguide.batch;
import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import org.hibernate.CacheMode;
import org.hibernate.ScrollMode;
import org.hibernate.ScrollableResults;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.StatelessSession;
import org.hibernate.Transaction;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.resource.transaction.spi.TransactionStatus;
import org.hibernate.userguide.model.Call;
import org.hibernate.userguide.model.Partner;
import org.hibernate.userguide.model.Person;
import org.hibernate.userguide.model.Phone;
import org.junit.Test;
import org.jboss.logging.Logger;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
import static org.junit.Assert.assertEquals;
/**
* @author Vlad Mihalcea
*/
public class BatchTest extends BaseEntityManagerFunctionalTestCase {
private static final Logger log = Logger.getLogger( BatchTest.class );
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] {
Person.class,
Phone.class,
Call.class,
Partner.class
};
}
@Test
public void testScroll() {
withScroll();
}
@Test
public void testStatelessSession() {
withStatelessSession();
}
@Test
public void testBulk() {
doInJPA( this::entityManagerFactory, entityManager -> {
entityManager.persist( new Person( "Vlad" ) );
entityManager.persist( new Person( "Mihalcea" ) );
} );
doInJPA( this::entityManagerFactory, entityManager -> {
String oldName = "Vlad";
String newName = "Alexandru";
//tag::batch-session-jdbc-batch-size-example[]
entityManager
.unwrap( Session.class )
.setJdbcBatchSize( 10 );
//end::batch-session-jdbc-batch-size-example[]
} );
doInJPA( this::entityManagerFactory, entityManager -> {
String oldName = "Vlad";
String newName = "Alexandru";
//tag::batch-bulk-jpql-update-example[]
int updatedEntities = entityManager.createQuery(
"update Person p " +
"set p.name = :newName " +
"where p.name = :oldName" )
.setParameter( "oldName", oldName )
.setParameter( "newName", newName )
.executeUpdate();
//end::batch-bulk-jpql-update-example[]
assertEquals(1, updatedEntities);
} );
doInJPA( this::entityManagerFactory, entityManager -> {
String oldName = "Alexandru";
String newName = "Vlad";
Session session = entityManager.unwrap( Session.class );
//tag::batch-bulk-hql-update-example[]
int updatedEntities = session.createQuery(
"update Person " +
"set name = :newName " +
"where name = :oldName" )
.setParameter( "oldName", oldName )
.setParameter( "newName", newName )
.executeUpdate();
//end::batch-bulk-hql-update-example[]
assertEquals(1, updatedEntities);
} );
doInJPA( this::entityManagerFactory, entityManager -> {
String oldName = "Vlad";
String newName = "Alexandru";
Session session = entityManager.unwrap( Session.class );
//tag::batch-bulk-hql-update-version-example[]
int updatedEntities = session.createQuery(
"update versioned Person " +
"set name = :newName " +
"where name = :oldName" )
.setParameter( "oldName", oldName )
.setParameter( "newName", newName )
.executeUpdate();
//end::batch-bulk-hql-update-version-example[]
assertEquals(1, updatedEntities);
} );
doInJPA( this::entityManagerFactory, entityManager -> {
String name = "Alexandru";
//tag::batch-bulk-jpql-delete-example[]
int deletedEntities = entityManager.createQuery(
"delete Person p " +
"where p.name = :name" )
.setParameter( "name", name )
.executeUpdate();
//end::batch-bulk-jpql-delete-example[]
assertEquals(1, deletedEntities);
} );
doInJPA( this::entityManagerFactory, entityManager -> {
Session session = entityManager.unwrap( Session.class );
//tag::batch-bulk-hql-insert-example[]
int insertedEntities = session.createQuery(
"insert into Partner (id, name) " +
"select p.id, p.name " +
"from Person p ")
.executeUpdate();
//end::batch-bulk-hql-insert-example[]
assertEquals(1, insertedEntities);
} );
doInJPA( this::entityManagerFactory, entityManager -> {
String name = "Mihalcea";
Session session = entityManager.unwrap( Session.class );
//tag::batch-bulk-hql-delete-example[]
int deletedEntities = session.createQuery(
"delete Person " +
"where name = :name" )
.setParameter( "name", name )
.executeUpdate();
//end::batch-bulk-hql-delete-example[]
assertEquals(1, deletedEntities);
} );
}
private void withoutBatch() {
//tag::batch-session-batch-example[]
EntityManager entityManager = null;
EntityTransaction txn = null;
try {
entityManager = entityManagerFactory().createEntityManager();
txn = entityManager.getTransaction();
txn.begin();
for ( int i = 0; i < 100_000; i++ ) {
Person Person = new Person( String.format( "Person %d", i ) );
entityManager.persist( Person );
}
txn.commit();
} catch (RuntimeException e) {
if ( txn != null && txn.isActive()) txn.rollback();
throw e;
} finally {
if (entityManager != null) {
entityManager.close();
}
}
//end::batch-session-batch-example[]
}
private void withBatch() {
int entityCount = 100;
//tag::batch-session-batch-insert-example[]
EntityManager entityManager = null;
EntityTransaction txn = null;
try {
entityManager = entityManagerFactory().createEntityManager();
txn = entityManager.getTransaction();
txn.begin();
int batchSize = 25;
for ( int i = 0; i < entityCount; ++i ) {
Person Person = new Person( String.format( "Person %d", i ) );
entityManager.persist( Person );
if ( i > 0 && i % batchSize == 0 ) {
//flush a batch of inserts and release memory
entityManager.flush();
entityManager.clear();
}
}
txn.commit();
} catch (RuntimeException e) {
if ( txn != null && txn.isActive()) txn.rollback();
throw e;
} finally {
if (entityManager != null) {
entityManager.close();
}
}
//end::batch-session-batch-insert-example[]
}
private void withScroll() {
withBatch();
//tag::batch-session-scroll-example[]
EntityManager entityManager = null;
EntityTransaction txn = null;
ScrollableResults scrollableResults = null;
try {
entityManager = entityManagerFactory().createEntityManager();
txn = entityManager.getTransaction();
txn.begin();
int batchSize = 25;
Session session = entityManager.unwrap( Session.class );
scrollableResults = session
.createQuery( "select p from Person p" )
.setCacheMode( CacheMode.IGNORE )
.scroll( ScrollMode.FORWARD_ONLY );
int count = 0;
while ( scrollableResults.next() ) {
Person Person = (Person) scrollableResults.get( 0 );
processPerson(Person);
if ( ++count % batchSize == 0 ) {
//flush a batch of updates and release memory:
entityManager.flush();
entityManager.clear();
}
}
txn.commit();
} catch (RuntimeException e) {
if ( txn != null && txn.isActive()) txn.rollback();
throw e;
} finally {
if (scrollableResults != null) {
scrollableResults.close();
}
if (entityManager != null) {
entityManager.close();
}
}
//end::batch-session-scroll-example[]
}
private void withStatelessSession() {
withBatch();
//tag::batch-stateless-session-example[]
StatelessSession statelessSession = null;
Transaction txn = null;
ScrollableResults scrollableResults = null;
try {
SessionFactory sessionFactory = entityManagerFactory().unwrap( SessionFactory.class );
statelessSession = sessionFactory.openStatelessSession();
txn = statelessSession.getTransaction();
txn.begin();
scrollableResults = statelessSession
.createQuery( "select p from Person p" )
.scroll(ScrollMode.FORWARD_ONLY);
while ( scrollableResults.next() ) {
Person Person = (Person) scrollableResults.get( 0 );
processPerson(Person);
statelessSession.update( Person );
}
txn.commit();
} catch (RuntimeException e) {
if ( txn != null && txn.getStatus() == TransactionStatus.ACTIVE) txn.rollback();
throw e;
} finally {
if (scrollableResults != null) {
scrollableResults.close();
}
if (statelessSession != null) {
statelessSession.close();
}
}
//end::batch-stateless-session-example[]
}
private void processPerson(Person Person) {
if ( Person.getId() % 1000 == 0 ) {
log.infof( "Processing [%s]", Person.getName());
}
}
}