JPA Transaction not committed to DB

12,027

Solution 1

The reason it is probably not working is because you are using @Transactional on a private method. @Transactional will have no effect on a non-public method, because the proxy generator ignores them. From the Spring Documentation:

Method visibility and @Transactional

When using proxies, you should apply the @Transactional annotation only to methods with public visibility. If you do annotate protected, private or package-visible methods with the @Transactional annotation, no error is raised, but the annotated method does not exhibit the configured transactional settings. Consider the use of AspectJ (see below) if you need to annotate non-public methods.

Solution 2

I was having a similar issue, and for me the fix came from the following:

In PersistenceXML:

<property name="hibernate.transaction.manager_lookup_class"
value="org.hibernate.transaction.JBossTransactionManagerLookup">

Spring file:

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="nameOfUnitInPersistenceXml" />
</bean>

<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
    <property name="transactionManagerName" value="java:/TransactionManager" />
</bean>

Java class (name the persistence context)

private EntityManager em;

@PersistenceContext(name="nameOfUnitInPersistenceXml")
public void setEntityManager(EntityManager em) {
    this.em = em;
}
Share:
12,027
forhas
Author by

forhas

Updated on September 13, 2022

Comments

  • forhas
    forhas over 1 year

    I'm working on a small Spring-Hibernate-Mysql test project and for some reason I my transactions are not getting committed to the DB.

    In my application-context I got:

    <!-- JTA -->
    
    <bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    
    </bean>
    
    <tx:annotation-driven transaction-manager="txManager" />
    
    <!-- JPA -->
    
    <jee:jndi-lookup id="entityManagerFactory" jndi-name="persistence/myPU" />
    
    <!-- In order to enable EntityManager injection -->
    <bean
        class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor">
        <property name="persistenceUnits">
            <map>
                <entry key="myPU" value="persistence/myPU" />
            </map>
        </property>
    </bean>
    

    My persistence.xml:

    <persistence-unit name="myPU" transaction-type="JTA">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <jta-data-source>jdbc/mysqlResource</jta-data-source>
        <properties>
            <property name="hibernate.connection.shutdown" value="true" />
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLInnoDBDialect"></property>
            <property name="hibernate.show_sql" value="true" />
        </properties>
    </persistence-unit>
    

    I created a simple table called 'persons' in my db:

    CREATE TABLE persons(
    id VARCHAR(255) PRIMARY KEY,
    version int, 
    full_name VARCHAR(255),
    person_id VARCHAR(255),
    email VARCHAR(255));
    

    Created entity a corresponding entity and Dao:

    @Entity
    @Table(name = "persons")
    public class Person implements Serializable {
    
    private static final long serialVersionUID = 4349832844316517922L;
    
    /*--- Members ---*/
    
    /**
     * Hibernate genetared UUID
     */
    @Id
    @GeneratedValue(generator = "system-uuid")
    @GenericGenerator(name = "system-uuid", strategy = "uuid")
    private String id;
    
    @Version
    private int version;
    
    @Column(name = "full_name")
    private String fullName;
    
    @Column(name = "person_id")
    private String personId;
    
    @Column(name = "email")
    private String eMail;
    
    /*--- Constructor ---*/
    
    public Person() {
    }
    
    /*--- Overridden Methods ---*/
    
    @Override
    public boolean equals(Object obj) {
    
        if ((obj == null) || !(obj instanceof Person)) {
            return false;
        }
    
        // reference comparison
        if (obj == this) {
            return true;
        }
    
        final Person other = (Person) obj;
    
        return new EqualsBuilder().append(getPersonId(), other.getPersonId())
                .append(geteMail(), other.geteMail())
                .append(getFullName(), other.getFullName()).isEquals();
    }
    
    /**
     * The unique hash code based on the clients' id and citizenship
     * 
     * {@inheritDoc}
     */
    @Override
    public int hashCode() {
    
        return new HashCodeBuilder().append(geteMail()).append(this.geteMail())
                .append(this.getFullName()).toHashCode();
    }
    
    /*--- Getters & Setters ---*/
    
    public String getId() {
        return id;
    }
    
    public void setId(String id) {
        this.id = id;
    }
    
    public int getVersion() {
        return version;
    }
    
    public void setVersion(int version) {
        this.version = version;
    }
    
    public String getFullName() {
        return fullName;
    }
    
    public void setFullName(String fullName) {
        this.fullName = fullName;
    }
    
    public String getPersonId() {
        return personId;
    }
    
    public void setPersonId(String personId) {
        this.personId = personId;
    }
    
    public String geteMail() {
        return eMail;
    }
    
    public void seteMail(String eMail) {
        this.eMail = eMail;
    }
    

    }

    Dao:

    @Repository
    public class PersonJpaDao extends BasicJpaDao<Person> implements IPersonDao {
    
    public PersonJpaDao() {
        super(Person.class);
    }
    

    }

    here is BasicJpaDao:

    public class BasicJpaDao<T> implements IBasicDao<T> {
    
    /* --- Members --- */
    
    /** The JPA utility to work with the persistence layer. */
    @PersistenceContext
    protected EntityManager entityManager;
    
    /** The type of the entity to which this DAO offers access. */
    protected Class<T> entityClass;
    
    /* --- Constructors --- */
    
    /**
     * Default constructor.
     * 
     * @param entityClass
     *            The type of the entity to which this DAO offers access.
     */
    public BasicJpaDao(Class<T> entityClass) {
        super();
        this.entityClass = entityClass;
    }
    
    /* --- Public methods --- */
    
    /**
     * {@inheritDoc}
     */
    @Override
    public void create(T entity) {
        getEntityManager().persist(entity);
    }
    
    /**
     * {@inheritDoc}
     */
    @Override
    public T read(Object primaryKey) {
        return getEntityManager().find(getEntityClass(), primaryKey);
    }
    
    /**
     * {@inheritDoc}
     */
    @Override
    public T update(T entity) {
        return getEntityManager().merge(entity);
    }
    
    /**
     * {@inheritDoc}
     */
    @Override
    public void delete(T entity) {
        getEntityManager().remove(entity);
    }
    
    /**
     * {@inheritDoc}
     */
    @Override
    public void flush() {
        getEntityManager().flush();
    }
    
    /* --- Getters/Setters --- */
    
    /**
     * @return The JPA utility to work with the persistence layer.
     */
    public EntityManager getEntityManager() {
        return this.entityManager;
    }
    
    /**
     * @param entityManager
     *            The JPA utility to work with the persistence layer.
     */
    public void setEntityManager(EntityManager entityManager) {
        this.entityManager = entityManager;
    }
    
    /**
     * @return The type of the entity to which this DAO offers access.
     */
    public Class<T> getEntityClass() {
        return entityClass;
    }
    
    /**
     * @param entityClass
     *            The type of the entity to which this DAO offers access.
     */
    public void setEntityClass(Class<T> entityClass) {
        this.entityClass = entityClass;
    }
    

    Soo.. basically it works, but nothing gets committed, I mean, if I run

    @Transactional(propagation = Propagation.REQUIRED)
    private void crearePerson() {
        Person p1 = myDao.read("12345");
        p1.setFullName("kiko too");
        myDao.update(p1);
    }
    

    I can see (in debug) that p1 gets back from the DB but the update never takes place. The only close thing I could find was this:

    JPA - transactions not being committed

    And I tried adding

    <property name="hibernate.connection.shutdown" value="true" />
    

    to my persistence.xml following this thread but it didn't help. I also added a property to my connection pool (in my application server gui) called connection.shutdown with the value of true but it didn't help either.

    Update: Since I'm using JTA I figured my transaction manager is wrongly configured. While I was using org.springframework.orm.jpa.JpaTransactionManager I should have used org.springframework.transaction.jta.JtaTransactionManager. So I have changed my application context and now I have:

    <bean id="txManager"
        class="org.springframework.transaction.jta.JtaTransactionManager" />
    
    <tx:annotation-driven transaction-manager="txManager" />
    

    Unfortunately, I'm still experiencing the same issue :( In my console I can see the hibernate query as follows ()I've changed some of my original entity fields, but it doesn't really matters):

    INFO: Hibernate: select user0_.id as id0_0_, user0_.email as email0_0_, user0_.full_name as full3_0_0_, user0_.password as password0_0_, user0_.update_by_email as update5_0_0_, user0_.user_name as user6_0_0_, user0_.version as version0_0_ from users user0_ where user0_.id=?

    Any ideas?

    Thanks in advance, Yogi