声明式事务(@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.xmlcomponent-scancomponent-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