问题描述
我正在尝试使用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中的
还在其扫描中包含您的DAO类,因此在其应用程序上下文(而不是数据库)中为它们创建实例...以便当您的Web从Web控制器访问这些DAO时,它正在访问它们的非事务版本(除非您添加组件扫描
.xml 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-package
configuration 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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!