6

假设我们有以下代码:

@Entity
public class User {
    @Id
    private String name;
    @OneToOne(cascade = CascadeType.ALL)
    private Address address;
    //getters and setters
}

@Entity
public class Address {
    @Id
    private int id;
    private String street;
    //getters and setters
}

@Stateless
//@Service
public class UserLogicClass {
    @PersistenceContext
    //@Autowired
    private EntityManager entityManager;

    public void logicOnUser(User user) {
        if(logicOnAddress(user.getAddress()) {
            otherLogicOnUser(user);
        }
    }

    public boolean logicOnAddress(Address address) {
        //
        entityManager.find(address);//address becomes managed
        //
    }

    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
    //@Transactional(propagation = Propagation.REQUIRES_NEW)
    public void otherLogicOnUser
    //
        entityManager.find(user);/*without annotation, user is not managed and address is managed, but with the transaction annotation is the address still managed?*/
    //
    }
}

问题依赖于最后一种方法的评论;我很好奇 Spring 案例和 EJB 案例中会发生什么。假设 Spring 配置了 JTA 事务,并且从此类调用的任何方法都将启动一个新事务,就像在 EJB 中一样。

4

2 回答 2

6

这更多是JPA的问题。除非您对其进行扩展,否则 entityManager 不会传播到新事务:

@PersistenceContext(type = PersistenceContextType.EXTENDED)
//@Autowired
private EntityManager entityManager;

引用 JPA 2.0 规范:

容器管理的持久性上下文可以定义为具有范围为单个事务的生命周期或跨越多个事务的扩展生命周期,这取决于创建其实体管理器时指定的 PersistenceContextType。本规范将此类持久性上下文分别称为事务范围持久性上下文和扩展持久性上下文。

于 2013-04-27T06:45:15.987 回答
4

注意:由于这种机制是基于代理的,只有通过代理传入的“外部”方法调用才会被拦截。这意味着“自调用”,即目标对象中的一个方法调用目标对象的其他方法,即使调用的方法标有@Transactional,也不会在运行时导致实际事务!

在目标对象内部调用 otherLogicOnUser()。

阅读更多:本地方法调用中的 EJB 事务

于 2013-04-27T06:48:44.463 回答