Spring @Transactional не создает транзакции

Я серьезно бьюсь головой о стену весенними транзакциями. Я искал несколько дней, пытаясь заставить @Transactional работать. Любая помощь будет высоко ценится!

Я использую Spring 3.2 для веб-приложения, обращающегося к базе данных MySQL (я использую Spring MVC, JDBC и Security). Таблицы mysql используют InnoDB. Я изо всех сил пытаюсь заставить декларативные транзакции работать (я попытался использовать программные транзакции, и это работало успешно). У меня есть контроллеры, вызывающие сервисные методы, которые аннотируются @Transactional. Контроллеры настраиваются в XML-файле сервлета, а службы / Dao настраиваются в отдельном XML-файле приложения. Кажется, я не могу подобрать правильную конфигурацию для @Transactional и создать транзакции. Там нет ошибок - просто нет транзакций. Вот детали моей настройки:

  1. Веб-приложение, использующее DispatcherServlet, настроенное с помощью файла XML сервлета с использованием аннотированных контроллеров. Контроллеры имеют сервисные интерфейсы.

  2. Методы обслуживания снабжены аннотациями @Transactional и DAO.

  3. Классы обслуживания снабжены аннотацией @Named, и приложение настроено на их поиск в spring-app-context.xml с помощью компонентного сканирования.

  4. Конфигурация транзакций настраивается в spring-app-context.xml (не в файле конфигурации сервлета).

web.xml:

<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>
    /WEB-INF/config/spring-app-context.xml
    /WEB-INF/config/spring-security-context.xml
  </param-value>
</context-param>

<listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<servlet>
  <servlet-name>appServlet</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/config/spring-servlet-context.xml</param-value>
  </init-param>
  <load-on-startup>1</load-on-startup>
</servlet>


<servlet-mapping>
  <servlet-name>appServlet</servlet-name>
  <url-pattern>/</url-pattern>
</servlet-mapping>

весна-сервлет-context.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->

    <!-- Scans within the base package of the application for @Components to configure as beans -->
    <!-- @Controller, @Service, @Configuration, etc. -->
    <context:component-scan base-package="ewarrants.web" />

    <!-- Enables the Spring MVC @Controller programming model -->
    <mvc:annotation-driven />

    <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views/" />
        <property name="suffix" value=".jsp" />
    </bean>

    <context:property-placeholder location="/WEB-INF/config/ewarrants.properties"/>

</beans>

Вот пример настройки контроллера:

@Inject
IUserService userService;

@RequestMapping(value = "/register", method = RequestMethod.POST)
public String processRegistration(@Valid @ModelAttribute UserRegistrationVM incomingVM, BindingResult result, Model model) throws Exception {       

    ...

    userService.registerNewUser(newUser);

    return "redirect:<location>";
}

Вот весна-приложение-контекст:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">


    <!-- Scans within the base package of the application for @Components to configure as beans -->
    <!-- @Controller, @Service, @Configuration, etc. -->
    <context:component-scan base-package="ewarrants.core" />
    <tx:annotation-driven transaction-manager="txManager" />

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="<url>"/>
        <property name="username" value="<user>"/>
        <property name="password" value="<password>"/> 
    </bean>

    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

    <context:property-placeholder location="/WEB-INF/config/ewarrants.properties"/>
</beans>

Вот пример реализации сервиса:

@Named
public class UserService extends Service implements IUserService {

    @Inject
    private IUserDao userDao;

    @Override
    @Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class)
    public void registerNewUser(User user) throws Exception {
        ...

        // add the user record
        int newUserID = userDao.insertUser(user);

        // carry out more database inserts
    }
}

0 ответов

Другие вопросы по тегам