Spring transactional context doesn't persist data

13,524

Solution 1

solved my problem using

org.springframework.orm.jpa.JpaTransactionManager

so your bean should be

 <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" />

hope this work!

Solution 2

In the version of the code that uses the JPA entity manager. Try adding an em.flush() after the em.persist() - all em.persist() does is to attach the entity to the persistence context. The entity is not 'persisted' at that point.

You should not need the em.flush() - but give it a try to see if it helps.

When the transaction ends then the persistence context should automatically be flushed (written to the db).

I have to say you've got quite a complicated setup here - you might need some trial & error to narrow it down. Adding JTA into the mix might not help matters - you could try with 'resource local' in Spring until you get it working. Are there any errors in the logs ?

Share:
13,524
Arek Woźniak
Author by

Arek Woźniak

JEE developer.

Updated on June 09, 2022

Comments

  • Arek Woźniak
    Arek Woźniak almost 2 years

    I know that my problem is a common problem, but I've checked a lot of questions here, checked Spring documentation and I really don't know what I am doing wrong. My problem: I've got a Spring WebFlow project using JPA (implementation: OpenJPA + MySQL database). I use Spring ORM to inject EntityManager (by @PersistenceContext annotation) to my simple RegisterDAO. I have configured GlassFishs (which I am using) connection pools for using MySQL and everything works - I can work with my database, but when I am persisting something - nothing happens (data are not persist to database). I know that problem is with transactional context which I use. I read the documentation of Spring Transaction Management and follow the configuration steps in this documentation. This is my applicationContext.xml:

    <?xml version="1.0" encoding="windows-1250"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:p="http://www.springframework.org/schema/p"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xmlns:jee="http://www.springframework.org/schema/jee"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
           http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
           http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.0.xsd">
    
        <jee:jndi-lookup id="entityManagerFactory" jndi-name="myPersistenceUnit"/> 
        <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
    
        <bean id="registerDaoImpl" class="umk.dumont.db.dao.RegisterDAO" />
        <bean id="registerModel" class="umk.dumont.models.RegisterFormModel">
            <property name="registerDAO" ref="registerDaoImpl" />
        </bean>
    
    
      <tx:advice id="txAdvice">
        <tx:attributes>
          <tx:method name="*" />
        </tx:attributes>
      </tx:advice> 
    
      <aop:config>
        <aop:pointcut id="registerModelOperation" expression="execution(* umk.dumont.models.RegisterFormModel.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="registerModelOperation"/>
      </aop:config>
    
      <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager" />
    
    
    </beans>
    

    As you can see I am injecting RegisterDAO into my RegisterFormModel, which contains my business logic for validating register form data and eventually adding user to database. Validating works fine, the problem occurs when I am trying to add new user. Here is the code:

    package umk.dumont.models;
    
    ...
    
    public class RegisterFormModel implements Serializable {
        private String login;
        private String password;
        private String email;
        @Autowired
        private RegisterDAO registerDAO = null;
    
    ...
    
    public boolean addUser()
        {
            MyUser user = new MyUser();
            user.setLogin(login);
            user.setPassword(password);
            user.setEmail(email);
            return registerDAO.insertUserIntoDB(user) == 0 ? true : false;
        }
    
    ...
    }
    

    RegisterDAO:

    public class RegisterDAO implements RegisterDAOInterface, Serializable {
        private EntityManager em;
    
        @PersistenceContext
        public void setEm(EntityManager em)
        {
            this.em = em;
        }
    
    
    ...
    public int insertUserIntoDB(MyUser user)
        {
            int result = -4;
            try {
                em.persist(user);
                result = 0;
    
            }
            catch(Exception ex)
            {
                ex.printStackTrace();
                result = -4;
            }
            finally {
    
                return result;
            }
        }
    ...
    }
    

    I have also tried with @Transactional annotation. I configured spring applicationContext.xml like this:

    <?xml version="1.0" encoding="windows-1250"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:p="http://www.springframework.org/schema/p"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xmlns:jee="http://www.springframework.org/schema/jee"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
           http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
           http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.0.xsd">
    
    
    
        <jee:jndi-lookup id="entityManagerFactory" jndi-name="myPersistenceUnit"/> 
        <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
        <bean id="registerDaoImpl" class="umk.dumont.db.dao.RegisterDAO" />
        <bean id="registerModel" class="umk.dumont.models.RegisterFormModel">
            <property name="registerDAO" ref="registerDaoImpl" />
        </bean>
    
    
      <tx:annotation-driven />
      <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager" />
    
    
    </beans>
    

    and annotated my addUser() method with @Transactional annotation like this:

    package umk.dumont.models;
    
    ...
    
    public class RegisterFormModel implements Serializable {
        private String login;
        private String password;
        private String email;
        @Autowired
        private RegisterDAO registerDAO = null;
    
    ...
    @Transactional
    public boolean addUser()
        {
            MyUser user = new MyUser();
            user.setLogin(login);
            user.setPassword(password);
            user.setEmail(email);
            return registerDAO.insertUserIntoDB(user) == 0 ? true : false;
        }
    
    ...
    }
    

    or even annotated whole class by this annotation:

    package umk.dumont.models;
    
    ...
    @Transactional    
    public class RegisterFormModel implements Serializable {
        private String login;
        private String password;
        private String email;
        @Autowired
        private RegisterDAO registerDAO = null;
    
    ...
    public boolean addUser()
        {
            MyUser user = new MyUser();
            user.setLogin(login);
            user.setPassword(password);
            user.setEmail(email);
            return registerDAO.insertUserIntoDB(user) == 0 ? true : false;
        }
    
    ...
    }
    

    but in both cases problem is the same - data doesn't stored in database. Is there any problem with my AOP proxing, because I'm newbie in this (just like in whole Spring :))?

    EDIT: In my persistence.xml I am using transaction-type="JTA" so I think I should use <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager" /> in my applicationContext.xml - am I right?