Spring @Transactional 展示位置
Spring @Transactional placement
我最近在玩 Spring/JPA2 以更好地了解它的工作原理。在我的实验中,我发现了一些奇怪的行为。问题是:
为什么下面的代码运行良好(在db中添加确认记录):
@Repository
public class UserDAO {
@PersistenceContext
EntityManager em;
@Transactional
public void add(User user) {
doAdd(user);
}
public void doAdd(User user) {
em.persist(user);
}
}
但是下面的(@Transactional注解移到了内部方法):
@Repository
public class UserDAO {
@PersistenceContext
EntityManager em;
public void add(User user) {
doAdd(user);
}
@Transactional
public void doAdd(User user) {
em.persist(user);
}
}
抛出异常:
javax.persistence.TransactionRequiredException: No transactional EntityManager available
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:273)
at com.sun.proxy.$Proxy556.persist(Unknown Source)
at com.example.UserDAO.doAdd(UserDAO.java:24)
...
In proxy mode (which is the default), only external method calls
coming in through the proxy are intercepted. This means that
self-invocation, in effect, a method within the target object calling
another method of the target object, will not lead to an actual
transaction at runtime even if the invoked method is marked with
@Transactional.
@Transactional 注释支持通过将实际的 DAO 实例包装在代理中来工作,代理会拦截方法调用和 starts/commits 事务。在第二个示例中,实际的 UserDAO 实例正在调用 doSave 方法,因此没有代理来拦截方法调用。
我最近在玩 Spring/JPA2 以更好地了解它的工作原理。在我的实验中,我发现了一些奇怪的行为。问题是:
为什么下面的代码运行良好(在db中添加确认记录):
@Repository
public class UserDAO {
@PersistenceContext
EntityManager em;
@Transactional
public void add(User user) {
doAdd(user);
}
public void doAdd(User user) {
em.persist(user);
}
}
但是下面的(@Transactional注解移到了内部方法):
@Repository
public class UserDAO {
@PersistenceContext
EntityManager em;
public void add(User user) {
doAdd(user);
}
@Transactional
public void doAdd(User user) {
em.persist(user);
}
}
抛出异常:
javax.persistence.TransactionRequiredException: No transactional EntityManager available
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:273)
at com.sun.proxy.$Proxy556.persist(Unknown Source)
at com.example.UserDAO.doAdd(UserDAO.java:24)
...
In proxy mode (which is the default), only external method calls coming in through the proxy are intercepted. This means that self-invocation, in effect, a method within the target object calling another method of the target object, will not lead to an actual transaction at runtime even if the invoked method is marked with @Transactional.
@Transactional 注释支持通过将实际的 DAO 实例包装在代理中来工作,代理会拦截方法调用和 starts/commits 事务。在第二个示例中,实际的 UserDAO 实例正在调用 doSave 方法,因此没有代理来拦截方法调用。