我已经启用了spring应用程序来使用事务并相应地注释了我的服务方法,但是当抛出RuntimeException时,我的数据库的更改仍然存在。
My Spring配置如下所示:
<!-- Data Source. -->
<jee:jndi-lookup id="dataSource" jndi-name="java:/jdbc/BeheermoduleDS"/>
<!-- JPA Entity Manager. -->
<jee:jndi-lookup id="entityManagerFactory" jndi-name="java:/jpa/BeheermoduleDS"/>
<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="txManager" />
我的jboss配置文件中的数据源配置如下所示:
<datasource jta="true" jndi-name="java:/jdbc/BeheermoduleDS" pool-name="BeheermoduleDS" enabled="true" use-java-context="true" use-ccm="true">
<connection-url>jdbc:sqlserver://localhost:1433;databaseName=Gebruikers;</connection-url>
<driver>sqljdbc</driver>
<security>
<user-name>jboss</user-name>
<password>*****</password>
</security>
</datasource>
我的服务方法如下所示:
@Transactional
public void authorise(Gebruiker user) {
user.setStatus(GebruikerStatus.Actief.name());
gebruikerRepo.save(user);
if (true) {
throw new RuntimeException("Exception happened just like that");
}
// does more stuff here that is never reached
}
我的存储库扩展了一个spring数据存储库,如下所示:
public interface GebruikerRepository extends PagingAndSortingRepository<Gebruiker, Long>, QueryDslPredicateExecutor<Gebruiker> {
}
该事务被控制器抛出并捕获,该控制器仅向用户显示发生异常的消息。当我检查我的SQL Server数据库时,已经提交了对用户状态所做的更改。
是不是他们应该使用RuntimeException回滚?
在为 org.springframework.transaction.interceptor 打开调试之后,我发现没有为我的服务方法启动任何事务,但它们是针对一堆JpaRepository方法的。
此外,这是我的persistence.xml的样子:
<persistence-unit name="BeheermodulePU" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<non-jta-data-source>java:/jdbc/BeheermoduleDS</non-jta-data-source>
答案 0 :(得分:2)
从您描述的症状判断,您正在扫描两次相同的课程。在<context:component-scan />
和ContextLoaderListener
的配置中,您可能具有相同的DispatcherServlet
。
您希望ContextLoaderListener
仅针对@Controller
扫描除DispatcherServlet
和@Controllers
以外的所有内容。导致这样的事情。
对于ContextLoaderListener
<!-- Load everything except @Controllers -->
<context:component-scan base-package="com.myapp">
<context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
</context:component-scan>
对于DispatcherServlet
<!-- Load everything except @Controllers -->
<context:component-scan base-package="com.myapp" use-default-filters="false">
<context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
</context:component-scan>
另请参阅@Service are constructed twice了解另一个示例和更广泛的解释。