[英]Declarative transactions (@Transactional) doesn't work with @Repository in Spring
我正在尝试使用Spring,JPA和嵌入式H2数据库制作简单的应用程序。 最近,我在声明式事务中遇到了这个奇怪的问题。 如果我使用@Repository注释自动连接DAO,则它们不会提交。 更具体地说,我在刷新时出现异常:
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
@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;
}
}
@Repository
public class JpaDao {
@PersistenceContext
private EntityManager em;
@Transactional
public void addProfessor(Professor professor) {
em.persist(professor);
em.flush();
}
}
<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
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中显式指定它,则一切正常。
将另一个<tx:annotation-driven />
放入spring servlet config中可以解决此问题,但是为什么呢?
可能是因为spring-servlet.xml
的component-scan
还在其扫描中包括了DAO类,因此在其应用程序上下文中为它们创建了实例(而不是“数据库”类)...以便您的Web访问这些对象时来自Web控制器的DAO,它正在访问它们的非事务版本(除非您添加tx:annotation-driven
标签)。
因此,添加该标签实际上是一个不好的解决方案,因为它仍会在错误的应用程序上下文中创建您的DAO实例:更好地为您的Web层组件创建创建更具体的base-package
配置。
我遇到了同样的问题,因为我认为我的spring-servlet.xml
中的<context:include-filter>
仅负责扫描@Controller
类...但没有:-(
@Transactional
批注可以放在接口定义,接口上的方法,类定义或类上的公共方法之前。 但是,请注意,仅仅出现@Transactional
注解是不够的,真正打开事务行为-的@Transactional
注解很简单,可以用的东西,是要消耗的元数据@Transactional
知晓的,并且可以使用元数据来使用事务行为配置适当的bean。 在上面的示例中, <tx:annotation-driven/>
元素的存在开启了交易行为。
来自spring doc http://static.springsource.org/spring/docs/2.0.8/reference/transaction.html
只是一个猜测,但您无需注册自己的PersistenceAnnotationBeanPostProcessor
,因为<context:component-scan>
自动注册一个。 两者可能互相干扰。
就像我说的那样,只是预感。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.