【问题标题】:@Transactional on a public method called inside a Bean: HHH000437@Transactional 在 Bean 内部调用的公共方法上:HHH000437
【发布时间】:2015-03-14 02:52:30
【问题描述】:

我对 @Transactional 注释有奇怪的行为。该代码与 caller 上的 @Transactional 配合良好:

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);
}

但以下实现在第二个 em.persist 上返回 错误被调用者上带有 @Transactional:

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. 
}

返回错误:

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])

有人有想法吗?

谢谢!

【问题讨论】:

  • Spring使用代理来应用AOP,这基本上意味着只有方法调用INTO(外部)对象检索AOP,内部方法调用通过代理。

标签: spring jpa transactional


【解决方案1】:

我认为这是因为 Spring 在您的类周围创建代理 bean,并且只有代理的方法通过注释行为得到增强。当你注解一个私有方法时,它是从你的类内部调用的,不能通过代理调用,导致注解被忽略。

@M。我认为 Deinum 是对的,是我答案的更正版本。所以,只有注解的方法有事务支持,但只有如果通过spring代理调用。如果你从 bean 本身调用它,就像你做的那样,它不会工作。

为了让它工作,你必须使用这样的东西

context.getBean(MyBean.class).callee(login);

【讨论】:

  • 对不起,我的问题有一个错误:两种方法都是公开的,没有私有的
  • 方法是否私有(我们可以看到它是公共的)并不重要。相反,这意味着这是一个 bean 实现类,并且接口没有第二个 callee 方法。在这种情况下,Spring AOP 无法代理该方法。是这样吗?
  • @Steve 第二种方法在原始问题中是私有的。无论如何,你的理论对我来说很有意义。
  • btw - 可能值得考虑启用 AspectJ 代理。如果您使用 XML 配置,只需添加 &lt;aop:aspectj-autoproxy/&gt; 或为 Java 配置添加 @EnableAspectJAutoProxy。这样,您将获得编译时代码编织,而不是依赖于接口的动态代理。
  • 谢谢大家!所以回答你,这个bean没有接口,但也许添加一个接口来实现会解决这个问题。待测试!
猜你喜欢
  • 2016-06-06
  • 1970-01-01
  • 2010-10-17
  • 1970-01-01
  • 2020-01-15
  • 1970-01-01
  • 1970-01-01
  • 2017-03-25
相关资源
最近更新 更多