【发布时间】:2020-03-02 17:01:10
【问题描述】:
免责声明:是的,我知道 @Transactional 应该只放在 Service 方法上,理想情况下。
我正在支持一个陈旧且设计不佳的应用程序,其中所有业务逻辑都在 Controller 方法中杂乱无章,并且这些方法不是事务性的,因此错误不会触发回滚并且数据已损坏。
我们的团队需要快速修复以启用此旧应用程序的错误回滚,因此决定将 @Transactional 放在 Controller 方法上(而不是重构应用程序,这将是一项重大工作)。
但是,当我在 Controller 方法上尝试以下操作时,它并没有回滚我的异常:
@Controller
public class ReviewDetailsController extends BaseController{
@RequestMapping(value={"/testException"}, method = RequestMethod.POST)
@Transactional(readOnly = false, rollbackFor = Exception.class)
public void testException(@RequestParam(required = true) String planId) throws Exception {
// Simulate some simple DB change: we'll change a Date to a dummy value, 03:33:33
Plans plan = planService.findById(new Integer(planId));
PlanWorkflow pw = processService.getLatestWorkflow(plan);
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
Date d = sdf.parse("12/06/2019 03:33:33");
pw.setCreatedDate(d);
// Save it
processService.savePlanWorkflow(pw);
// Exception test
throw new Exception("EXCEPTION TEST");
}
另一方面,当将完全相同的逻辑放入示例服务类方法中时,它确实成功回滚。
Controller现在调用Service方法,Service方法有@Transactional
@RequestMapping(value={"/testException"}, method = RequestMethod.POST)
@Transactional(readOnly = false, rollbackFor = Exception.class)
public void testException(@RequestParam(required = true) String planId) throws Exception {
// Call a Service method with the exact same logic from the Controller
processService.testException(planId);
}
服务
@Component
public class ProcessServiceImpl implements ProcessService {
@Override
@Transactional(readOnly = false, rollbackFor = Exception.class)
public void testException(@RequestParam(required = true) String planId) throws Exception {
// Simulate some simple DB change: we'll change a Date to a dummy value, 03:33:33
Plans plan = planService.findById(new Integer(planId));
PlanWorkflow pw = processService.getLatestWorkflow(plan);
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
Date d = sdf.parse("12/06/2019 03:33:33");
pw.setCreatedDate(d);
// Save it
processService.savePlanWorkflow(pw);
// Exception test
throw new Exception("EXCEPTION TEST");
}
理论上,每个人都说我应该能够将@Transactional 附加到 Controller 方法(尽管不建议这样做——但我仍然应该能够做到)。那么为什么 Controller 方法不接受它或尊重它呢?
applicationContext:
<context:component-scan base-package="mypackage.myapp">
</context:component-scan>
<jpa:repositories base-package="mypackage.myapp.dao"/>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="/META-INF/persistence.xml"/>
</bean>
<cache:annotation-driven/>
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager"
p:cache-manager-ref="ehcache"/>
<bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
p:config-location="/WEB-INF/ehcache.xml"/>
我尝试过的事情:
- 使控制器实现一个接口,以启用“JDK 代理”。现在是控制器
implementsControllerInterface,其中方法签名已被提取(Source -> Refactor -> Extract Interface in Eclipse)。 - 添加
<aop:aspectj-autoproxy proxy-target-class="true" />以启用“CGLIB 代理”。
但是这些都没有帮助。数据仍未从 Controller 中回滚。
类似线程:1。没有提供解决方案。
【问题讨论】:
-
谢谢,这里是:
<spring.version>4.3.12.RELEASE</spring.version> -
在
@Controller之后添加@Transactional注解 -
没用....
标签: java spring spring-mvc spring-data-jpa