Announcement Announcement Module
Collapse
No announcement yet.
Differences in Transactionmanagement Hibernate and JPA Transactionmanager Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Differences in Transactionmanagement Hibernate and JPA Transactionmanager

    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:

    Code:
    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:

    Code:
    @Transactional
    	public void saveTestEntity(TestEntity entity)
    	{
    		getTestRepository().saveTestEntity(entity);
    	}
    repository method:

    Code:
    	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:

    Code:
    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:
    Code:
    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):
    Code:
    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
    Last edited by TheFriedC; Jan 10th, 2012, 04:40 AM. Reason: additional info to DAOs

  • #2
    Found the crux

    i found the source of the different behavior in the Hibernate/JPA templates.

    HibernateTemplate extends the class HibernateAccessor, which implements the following method:

    Code:
    protected void flushIfNecessary(Session session, boolean existingTransaction) throws HibernateException {
    		if (getFlushMode() == FLUSH_EAGER || (!existingTransaction && getFlushMode() != FLUSH_NEVER)) {
    			logger.debug("Eagerly flushing Hibernate session");
    			session.flush();
    		}
    	}
    So even if there is no EAGER flushMode and no active transaction the session is flushed if the flushMode is NOT NEVER.

    The difference now lies in the JpaTemplate, which extends the class JpaAccessor

    Code:
    protected void flushIfNecessary(EntityManager em, boolean existingTransaction) throws PersistenceException {
    		if (isFlushEager()) {
    			logger.debug("Eagerly flushing JPA entity manager");
    			em.flush();
    		}
    	}
    here it is just flushed if flushMode is explicitly set to EAGER.

    i hope this can help anyone.

    cheers, chris

    Comment

    Working...
    X