1

我正在用 Spring 交易认真地敲打我的头。我已经搜索了几天试图让@Transactional 工作。任何帮助将不胜感激!

我正在将 Spring 3.2 用于访问 MySQL 数据库的 Web 应用程序(我正在使用 Spring MVC、JDBC 和 Security)。mysql 表使用 InnoDB。我正在努力让声明性事务工作(我尝试使用程序化事务并且成功地工作)。我有控制器调用使用@Transactional 注释的服务方法。控制器在 servlet xml 文件中配置,服务/dao 在单独的应用程序 xml 文件中配置。我似乎找不到正确的配置来获取 @Transactional 并创建事务。没有错误 - 只是没有交易。以下是我的设置的详细信息:

  1. 使用 DispatcherServlet 的 Web 应用程序,配置有 servlet XML 文件,使用带注释的控制器。控制器注入了服务接口。

  2. 服务方法使用 @Transactional 注释并调用注入的 DAO 类。

  3. 服务类使用 @Named 进行注释,应用程序配置为使用组件扫描在 spring-app-context.xml 中获取这些。

  4. 事务配置在 spring-app-context.xml 中设置(不在 servlet 配置文件中)。

网页.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>

spring-servlet-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>";
}

这是spring-app-context:

<?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
    }
}
4

0 回答 0