JPA Transaction not committed to DB
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;
}
forhas
Updated on September 13, 2022Comments
-
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