TheFriedC
Jan 10th, 2012, 04:03 AM
hi!
i got a simple test-application for finding out some differences in transaction-behavior between using native hibernate and the hibernate implementation of JPA because i want to switch an application from pure hibernate
to JPA 2.0
i made this tes app because, when using hibernate (sessionfactory/hibernatetransactionmanager) it is not necessary to put a @Transactional annotation to a method to persist an entity. in jpa (from hibernate) nothing will be persisted without the @Transactional
there is one config using hibernate SessionFactory and spring's HibernateTransactionManager both using the same datasource bean
the other config uses a LocalContainerEntityManagerFactoryBean and JPATransactionManager.
i also use the hibernate/jpa templates provided by spring for data access. these are used by a repository class and the repository class is accessed by a facade.
in the facade, i put a @Transactional annotation on the required methods. therefore i discovered confusing behavior.
here the methods i use in the tests:
method for testing the behavior:
public void writeNewTestEntityToDB()
{
TestEntity te = new TestEntity();
te.setName("hi!");
te.setHistory(new EntityHistory(new Date(), 1L));
getFacade().saveTestEntity(te);
getFacade().saveTestEntity(te);
getFacade().saveTestEntity(te);
}
facade method:
@Transactional
public void saveTestEntity(TestEntity entity)
{
getTestRepository().saveTestEntity(entity);
}
repository method:
public void saveTestEntity(TestEntity entity)
{
getGenericDAO().attach(entity);
}
the genericDAO is either using JPATemplate or HibernateTemplate. both then use the corresponding *.merge(E entity) method
please note that the sessionfactory is using an IdTransferringMergeEventListener (the result in CASE 1 is not surprising but CASE 2 is)
CASE 1 with SESSIONFACTORY AND @Transactional on facade-method:
The entity just gets persisted one time.
hibernate output:
Hibernate: insert into TestEntity (id, createdBy, createdOn, updatedBy, updatedOn, myEnum, name) values (null, ?, ?, ?, ?, ?, ?)
Hibernate: call identity()
Hibernate: select testentity0_.id as ...
Hibernate: select testentity0_.id as ...
CASE 2 with SESSIONFACTORY and WITHOUT @Transactional on facade-method:
There are three records in the db (which i expected as normal behavior)
hibernate output:
Hibernate: insert into TestEntity (id, createdBy, createdOn, updatedBy, updatedOn, myEnum, name) values (null, ?, ?, ?, ?, ?, ?)
Hibernate: call identity()
Hibernate: insert into TestEntity (id, createdBy, createdOn, updatedBy, updatedOn, myEnum, name) values (null, ?, ?, ?, ?, ?, ?)
Hibernate: call identity()
Hibernate: insert into TestEntity (id, createdBy, createdOn, updatedBy, updatedOn, myEnum, name) values (null, ?, ?, ?, ?, ?, ?)
Hibernate: call identity()
CASE 3 with EntityManagerFactory AND @Transactional on facade method:
There are three records in the db.
hibernate output (same as in CASE 2):
Hibernate: insert into TestEntity (id, createdBy, createdOn, updatedBy, updatedOn, myEnum, name) values (null, ?, ?, ?, ?, ?, ?)
Hibernate: call identity()
Hibernate: insert into TestEntity (id, createdBy, createdOn, updatedBy, updatedOn, myEnum, name) values (null, ?, ?, ?, ?, ?, ?)
Hibernate: call identity()
Hibernate: insert into TestEntity (id, createdBy, createdOn, updatedBy, updatedOn, myEnum, name) values (null, ?, ?, ?, ?, ?, ?)
Hibernate: call identity()
CASE 4 with EntityManagerFactory and WITHOUT @Transactional on facade method:
nothing is done here by hibernate. no output and no persisted objects.
CASE 3 and CASE 4 behave like i expected them to, but i do not understand why HibernateTransactionManager does not need @Transactional and behaves kind of weird to me.
what are the differences here? it is really confusing me and i do not understand why it is behaving this way.
can anyone please help me out?
thanks a lot!
chris
i got a simple test-application for finding out some differences in transaction-behavior between using native hibernate and the hibernate implementation of JPA because i want to switch an application from pure hibernate
to JPA 2.0
i made this tes app because, when using hibernate (sessionfactory/hibernatetransactionmanager) it is not necessary to put a @Transactional annotation to a method to persist an entity. in jpa (from hibernate) nothing will be persisted without the @Transactional
there is one config using hibernate SessionFactory and spring's HibernateTransactionManager both using the same datasource bean
the other config uses a LocalContainerEntityManagerFactoryBean and JPATransactionManager.
i also use the hibernate/jpa templates provided by spring for data access. these are used by a repository class and the repository class is accessed by a facade.
in the facade, i put a @Transactional annotation on the required methods. therefore i discovered confusing behavior.
here the methods i use in the tests:
method for testing the behavior:
public void writeNewTestEntityToDB()
{
TestEntity te = new TestEntity();
te.setName("hi!");
te.setHistory(new EntityHistory(new Date(), 1L));
getFacade().saveTestEntity(te);
getFacade().saveTestEntity(te);
getFacade().saveTestEntity(te);
}
facade method:
@Transactional
public void saveTestEntity(TestEntity entity)
{
getTestRepository().saveTestEntity(entity);
}
repository method:
public void saveTestEntity(TestEntity entity)
{
getGenericDAO().attach(entity);
}
the genericDAO is either using JPATemplate or HibernateTemplate. both then use the corresponding *.merge(E entity) method
please note that the sessionfactory is using an IdTransferringMergeEventListener (the result in CASE 1 is not surprising but CASE 2 is)
CASE 1 with SESSIONFACTORY AND @Transactional on facade-method:
The entity just gets persisted one time.
hibernate output:
Hibernate: insert into TestEntity (id, createdBy, createdOn, updatedBy, updatedOn, myEnum, name) values (null, ?, ?, ?, ?, ?, ?)
Hibernate: call identity()
Hibernate: select testentity0_.id as ...
Hibernate: select testentity0_.id as ...
CASE 2 with SESSIONFACTORY and WITHOUT @Transactional on facade-method:
There are three records in the db (which i expected as normal behavior)
hibernate output:
Hibernate: insert into TestEntity (id, createdBy, createdOn, updatedBy, updatedOn, myEnum, name) values (null, ?, ?, ?, ?, ?, ?)
Hibernate: call identity()
Hibernate: insert into TestEntity (id, createdBy, createdOn, updatedBy, updatedOn, myEnum, name) values (null, ?, ?, ?, ?, ?, ?)
Hibernate: call identity()
Hibernate: insert into TestEntity (id, createdBy, createdOn, updatedBy, updatedOn, myEnum, name) values (null, ?, ?, ?, ?, ?, ?)
Hibernate: call identity()
CASE 3 with EntityManagerFactory AND @Transactional on facade method:
There are three records in the db.
hibernate output (same as in CASE 2):
Hibernate: insert into TestEntity (id, createdBy, createdOn, updatedBy, updatedOn, myEnum, name) values (null, ?, ?, ?, ?, ?, ?)
Hibernate: call identity()
Hibernate: insert into TestEntity (id, createdBy, createdOn, updatedBy, updatedOn, myEnum, name) values (null, ?, ?, ?, ?, ?, ?)
Hibernate: call identity()
Hibernate: insert into TestEntity (id, createdBy, createdOn, updatedBy, updatedOn, myEnum, name) values (null, ?, ?, ?, ?, ?, ?)
Hibernate: call identity()
CASE 4 with EntityManagerFactory and WITHOUT @Transactional on facade method:
nothing is done here by hibernate. no output and no persisted objects.
CASE 3 and CASE 4 behave like i expected them to, but i do not understand why HibernateTransactionManager does not need @Transactional and behaves kind of weird to me.
what are the differences here? it is really confusing me and i do not understand why it is behaving this way.
can anyone please help me out?
thanks a lot!
chris