0

I have did a lot of search on the web and pages like this and this and this mostly suggested for using CMTTransactionFactory. However I am still unable to make it work (I wonder if it is because I am creating a EM using a LocalContainerEntityManagerFactoryBean instead of creating Hibernate session by LocalSessionFactoryBean)

My App Service looks something like:

@Transactional(propagation=Propagation.REQUIRES_NEW)
public class FooServiceImpl implements FooService {
  @Inject
  private FooRepository fooRepo;

  public void doSomething() {
    Foo foo = fooRepo.findBySomething(...);
    foo.setBar(...);
    //fooRepo.flush();     // un-comment to do manual-flushing
  }
}

Here is the snippet in my app ctx

<jee:jndi-lookup  id="dataSource" jndi-name="jdbc/fooDs" />

<bean id="transactionManager"
    class="org.springframework.transaction.jta.WebSphereUowTransactionManager" />

<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="databasePlatform" value="org.hibernate.dialect.Oracle10gDialect" />
        </bean>
    </property>
    <property name="persistenceUnitName" value="foo" />
    <property name="dataSource" ref="dataSource" />
    <property name="packagesToScan" value="com.foo" />
    <!--
      <property name="persistenceXmlLocation" value="classpath:/META-INF/test-persistence.xml" />
     -->
    <property name="jpaPropertyMap">
        <map>
            <entry key="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" />
              <entry key="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.WebSphereExtendedJTATransactionLookup" />
              <entry key="hibernate.transaction.factory_class" value="org.hibernate.transaction.CMTTransactionFactory"/>

            <entry key="hibernate.transaction.flush_before_completion"  value = "true" />
        </map>
    </property>
</bean>

I am making use of Spring Data JPA and after the entity is retrieved, I updated the content. If I am not flushing the repository manually (which means session/entityManager) manually, it simply discard my changes.

Can anyone give me some hints on what I have missed in the setting? Is there anything special to notice for using LocalContainerEntityManagerFactoryBean?

I tried to change the jpaProperty entry of manager_lookup_class to hibernate.transaction.jta.platform => org.hibernate.service.jta.platform.internal.WebSphereExtendedJtaPlatform but it does not help.

I also tried to use org.hibernate.transaction.JTATransactionFactory as transaction factory class, or even remove the transaction factory class. Such change seems makes Hibernate unable to pickup the transaction. When I am manually flushing the repository, it simply give me a javax.persistence.TransactionRequiredException with message no transaction is in progress

I am using Spring 3.1.2.RELEASE, JPA with Hibernate 4.1.6.Final, Websphere 8

Is there anyone using the above combination and have a working config that I can follow?


Edit: I have tried to inject EntityManager to the service to avoid using Spring Data JPA. The symptom is the same: I have to explicitly call entityManager.flush() to let Hibernate pickup the updated entities. At least we can take Spring Data out of picture :)

Adrian Shum
  • 38,812
  • 10
  • 83
  • 131

2 Answers2

0

I have raised discussion in other forum. Here is the link that contains the reason behind.

http://forum.springsource.org/showthread.php?131051-Auto-Flush-not-working-for-Spring-3-1-LocalEntityManagerFactoryBean-Hibernate-4-JTA

It is caused by, the above combination is going to setup the entity manager with transaction type being RESOURCE_LOCAL. This is not working with the above combination of libraries' version (while it works when using Spring 2.5 + Hibernate 3).

A workaround for the problem is to declare the transaction type being JTA (by providing a persistence.xml).

A better solution is provided in later version of Spring, which LocalEntityManagerFactoryBean provides a jtaDataSource property (https://jira.springsource.org/browse/SPR-9883)

Adrian Shum
  • 38,812
  • 10
  • 83
  • 131
0

Your issue is this entry.

<entry key="hibernate.transaction.factory_class" value="org.hibernate.transaction.CMTTransactionFactory"/>

Remove that and the auto flush works after the transaction has completed. Seems like with that entry added you have to manually call entity manager flush.

Michael Pralow
  • 6,560
  • 2
  • 30
  • 46