Отказ от ответственности: Да, я знаю, что @Transactional
в идеале следует ставить только на методы обслуживания.
Я поддерживаю старое и плохо спроектированное приложение, в котором все деловые логи c загроможден в методах 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");
}
С другой стороны, когда поместили те же самые логики c в пример метода класса обслуживания, он успешно откатился.
Контроллер теперь вызывает метод 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);
}
Service
@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
к методам контроллера (хотя это не рекомендуется - но я все еще должен быть в состоянии сделать это). Так почему же методы Контроллера не подберут или не соблюдают его?
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 Proxy». Теперь контроллер
implements
ControllerInterface
, где были извлечены сигнатуры метода (Source -> Refactor -> Extract Interface в Eclipse). - Добавьте
<aop:aspectj-autoproxy proxy-target-class="true" />
, чтобы включить «CGLIB Proxy».
Связанные темы, откуда я получил эти идеи: 1 , 2 .
Но ничего из этого не помогло. Данные по-прежнему не возвращаются с контроллера.
Аналогичный поток: 1 . Решение не предлагается.