I have strange behavior with @Transactional annotation. The code works well with @Transactional on the caller:
import org.springframework.transaction.annotation.Transactional;
private javax.persistence.EntityManager em;
@Transactional
public void caller(String login) {
callee(login);
}
public void callee(String login) {
user = new User(login);
em.persist(user);
userInfo = new UserInfo();
userInfo.setUser(user);
em.persist(userInfo);
}
But the following implementation returns an error on the second em.persist with @Transactional on the callee:
import org.springframework.transaction.annotation.Transactional;
private javax.persistence.EntityManager em;
public void caller(String login) {
callee(login);
}
@Transactional
public void callee(String login) {
user = new User(login);
em.persist(user);
userInfo = new UserInfo();
userInfo.setUser(user);
em.persist(userInfo); // ERROR: org.hibernate.action.internal.UnresolvedEntityInsertActions : HHH000437: Attempting to save one or more entities that have a non-nullable association with an unsaved transient entity. The unsaved transient entity must be saved in an operation prior to saving these dependent entities.
}
Error returned:
org.hibernate.action.internal.UnresolvedEntityInsertActions : HHH000437: Attempting to save one or more entities that have a non-nullable association with an unsaved transient entity. The unsaved transient entity must be saved in an operation prior to saving these dependent entities.
Unsaved transient entity: ([package.entities.User#<null>])
Dependent entities: ([[package.entities.UserInfo#<null>]])
Non-nullable association(s): ([package.entities.UserInfo.user])
Does someone have an idea ?
Thanks !
I think it's because Spring creates proxy beans around your classes, and only methods of a proxy are enhanced with annotated behavior. When you annotate a private method, it is called from within your class and can't be called through proxy, resulting in annotation being ignored.
@M. Deinum is right I think, corrected version of my answer. So, only the annotated method has the transaction support, but only if called through spring proxy. If you call it from the bean itself, as you do, it won't work.
In order for this to work, you would have to use something like this
context.getBean(MyBean.class).callee(login);