声明式事务(@Transactional)不适用于Spring中的@Repository [英] Declarative transactions (@Transactional) doesn't work with @Repository in Spring

查看:407
本文介绍了声明式事务(@Transactional)不适用于Spring中的@Repository的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Spring,JPA和嵌入式H2数据库进行简单的应用程序。最近我遇到了声明性交易这个奇怪的问题。如果我用@Repository注释自动装配我的DAO,它们就不会提交。更具体地说,我在flush上获得异常:

I'm trying to make simple application using Spring, JPA and embedded H2 database. Recently I've come across this strange issue with declarative transactions. They just doesn't commit if I autowire my DAO with @Repository annotation. More specifically I get exception on flush:

javax.persistence.TransactionRequiredException: 
Exception Description: No transaction is currently active

这是我的设置:

<persistence-unit name="schedulePU" transaction-type="RESOURCE_LOCAL">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <properties>
        <property name="javax.persistence.jdbc.driver" value="org.h2.Driver" />
        <property name="javax.persistence.jdbc.url" value="jdbc:h2:~/scheduleDB" />
        <property name="javax.persistence.jdbc.user" value="sa" />
        <property name="javax.persistence.jdbc.password" value="" />
        <property name="eclipselink.target-database" value="org.eclipse.persistence.platform.database.H2Platform" />
        <property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
        <property name="eclipselink.logging.level" value="FINE"/>
    </properties>
</persistence-unit>



实体



Entity

@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



DAO

@Repository
public class JpaDao {

    @PersistenceContext
    private EntityManager em;

    @Transactional
    public void addProfessor(Professor professor) {
        em.persist(professor);
        em.flush();
    }
}



database.xml(包含在root spring context中)



database.xml (included from root spring context)

<beans>
    <context:component-scan base-package="com.spybot.schedule.dao" />

    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="schedulePU" />
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>

    <tx:annotation-driven transaction-manager="transactionManager" />
</beans>



控制器



Controller

@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中明确指定它,一切正常。

And now the interesting part. If I remove @Repository annotation from DAO and specify it explicitly in database.xml, everything works fine.

将另一个< tx:annotation-driven /> 放入 spring servlet 配置修复问题,但为什么?

Putting another <tx:annotation-driven /> into spring servlet config fixes the problem, but why?

推荐答案

可能是因为 spring-servlet中的组件扫描 .xml 还在其扫描中包含您的DAO类,因此在其应用程序上下文(而不是数据库)中为它们创建实例...以便当您的Web从Web控制器访问这些DAO时,它正在访问它们的非事务版本(除非您添加 tx:annotation-driven 标记)。

Probably because the component-scan in your spring-servlet.xml is also including your DAO classes in its scanning and therefore creating instances for them in its application context (not the "database" one)... so that when your web accesses these DAOs from web controllers, it is accessing non-transactional versions of them (unless you add that tx:annotation-driven tag).

因此,添加该标记实际上是一个糟糕的解决方案,因为它仍然在错误的应用程序上下文中创建DAO实例:更好地为您的Web创建更具体的 base-package 配置层组件c reation。

Therefore, adding that tag is in fact a bad solution because it still creates your DAO instances in the wrong application context: better create a more specific base-packageconfiguration for your web layer component creation.

我遇到了同样的问题,因为我认为< context:include-filter> 在我的 spring-servlet.xml 只负责扫描 @Controller 类...但没有: - (

I had this same problem because I thought a <context:include-filter> in my spring-servlet.xml was taking care of only scanning @Controller classes... but no :-(

这篇关于声明式事务(@Transactional)不适用于Spring中的@Repository的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆