声明式事务(@Transactional)不适用于Spring中的@Repository
我正在尝试使用Spring,JPA和嵌入式H2数据库进行简单的应用程序。 最近我遇到了声明性交易这个奇怪的问题。 如果我使用@Repository注释自动assembly我的DAO,它们就不会提交。 更具体地说,我在flush上获得exception:
javax.persistence.TransactionRequiredException: Exception Description: No transaction is currently active
这是我的设置:
persistence.xml中
org.eclipse.persistence.jpa.PersistenceProvider false
实体
@Entity @Table(name = "Professors") public class Professor { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; private String name; public Professor() { } public Professor(String name) { this.name = name; } }
DAO
@Repository public class JpaDao { @PersistenceContext private EntityManager em; @Transactional public void addProfessor(Professor professor) { em.persist(professor); em.flush(); } }
database.xml(包含在根spring上下文中)
调节器
@Controller public class HomeController { @Inject JpaDao dao; @RequestMapping("/add") public @ResponseBody String add(String name) { Professor p = new Professor(name); dao.addProfessor(p); return ":)"; } }
现在是有趣的部分。 如果我从DAO中删除@Repository注释并在database.xml中显式指定它,一切正常。
更新
将另一个放入spring servlet配置中可以解决问题,但为什么呢?
可能是因为spring-servlet.xml
的component-scan
在component-scan
中也包括DAO类,因此在其应用程序上下文(而不是“数据库”)中为它们创建实例…这样当您的Web访问这些时来自Web控制器的DAO,它正在访问它们的非事务版本(除非您添加tx:annotation-driven
标记)。
因此,添加该标记实际上是一个糟糕的解决方案,因为它仍然在错误的应用程序上下文中创建DAO实例:更好地为Web层组件创建创建更具体的base-package
配置。
我有同样的问题,因为我认为我的spring-servlet.xml
中的
只负责扫描@Controller
类……但是没有:-(
只是猜测,但您不需要注册自己的PersistenceAnnotationBeanPostProcessor
,因为
自动注册一个。 这两者可能互相干扰。
就像我说的那样,只是预感。
@Transactional
注释可以放在接口定义,接口上的方法,类定义或类的公共方法之前。 但请注意,仅仅存在@Transactional
注释并不足以实际打开事务行为 – @Transactional
注释只是可以被@Transactional
-aware消费的元数据,并且可以使用元数据来实现使用事务行为配置适当的bean。 在上面的示例的情况下,存在打开事务行为的
元素。
来自spring doc http://static.springsource.org/spring/docs/2.0.8/reference/transaction.html