1

Trying to use Spring, Hibernate-OGM with MongoDB. However getting an issue with transactions. I know they are not supported by MongoDB however I want to use annotation @transactional so I dont have to do begin, commit.

Exception

org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is java.lang.IllegalStateException: A JTA EntityManager cannot use getTransaction()
at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:430)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:420)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:257)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:644)

DB context.xml

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="mongo-hibernate"/>    
  </bean>

  <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory"/>
  </bean>

  <tx:annotation-driven transaction-manager="transactionManager"/>

persistence.xml

<persistence-unit name="mongo-hibernate" transaction-type="JTA">
        <provider>org.hibernate.ogm.jpa.HibernateOgmPersistence</provider>

        <properties>
           <property name="hibernate.current_session_context_class" value="thread"/>                        
           <property name="hibernate.ogm.datastore.provider" value="mongodb"/>
           <property name="hibernate.ogm.datastore.grid_dialect" value="org.hibernate.ogm.datastore.mongodb.MongoDBDialect"/>           
           <property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.JTATransactionFactory"/>                
            <property name="hibernate.ogm.datastore.database" value="mongodbtest"/>
            <property name="hibernate.ogm.mongodb.database" value="mongodbtest"/>
            <property name="hibernate.ogm.mongodb.host" value="localhost"/>
            <property name="hibernate.ogm.mongodb.associations.store" value="IN_ENTITY"/>
        </properties>

    </persistence-unit>
</persistence>

DAO

@PersistenceContext
protected EntityManager entityManager;

@Transactional(readOnly = false)
public <E> void updateObject(E entity) {
   entityManager.persist(entity);
 }

any help is appreciated. Thank you

Dima
  • 1,045
  • 14
  • 23

2 Answers2

1

So far I moved a little further, I changed some files to:

DB context.xml

   <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="mongo-hibernate"/>    
  </bean>

  <bean class="com.arjuna.ats.jta.TransactionManager" factory-method="transactionManager" id="arjunaTransactionManager"/>
  <bean class="com.arjuna.ats.jta.UserTransaction" factory-method="userTransaction" id="arjunaUserTransaction"/>  

  <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
    <property name="transactionManager" ref="arjunaTransactionManager"/>
    <property name="userTransaction" ref="arjunaUserTransaction"/>
  </bean>

  <tx:annotation-driven transaction-manager="transactionManager"/>

DAO:

@PersistenceContext
protected EntityManager entityManager;

@Transactional(readOnly = false)
public <E> void updateObject(E entity) {

    Session session = entityManager.unwrap(Session.class);          
    org.hibernate.Transaction tx = session.getTransaction();  
    tx.begin();
    session.persist(entity);
    tx.commit();

}

This way eveything is working fine, however I would really like it to work more simplier like:

@Transactional(readOnly = false)
public <E> void updateObject(E entity) {
   entityManager.persist(entity);
 }

Any suggestions?

Dima
  • 1,045
  • 14
  • 23
  • Sorry for the necro but have you figured it out? I am struggling to get it to work as well with latest Hibernate OGM. Thanks – Dan Aug 25 '16 at 11:33
  • Basically there is nothing to figure out. MongoDB has no transaction support. U can do the same way as mentioned, for the standard sake I use everything I do when developing for transactions. However recently I switched to SPRING project for mongodb, I really like it so far. – Dima Aug 26 '16 at 13:24
  • Well actually I figured it out shortly after asking. The only thing that was wrong was that I wasn't using @Transactional in a Spring managed bean. And yes, MongoDB itself does not support transactions but they still suggest demarcating the operation ([link](http://docs.jboss.org/hibernate/ogm/5.0/reference/en-US/html_single/#on_flush_and_transactions)). – Dan Aug 26 '16 at 14:11
-2

Yup, I have a suggestion: Read the docs. ;)

"MongoDB does not support transaction."

Markus W Mahlberg
  • 19,711
  • 6
  • 65
  • 89
  • I read the docs, I know transactions are not supported, however hibernate guys still advice to use standard syntax @Transactional. – Dima Aug 31 '14 at 14:44
  • Here is a note from hibernate suggesting using @transactional even they are not supported http://docs.jboss.org/hibernate/ogm/4.0/reference/en-US/html_single/#_transactions – Dima Aug 31 '14 at 23:42