【问题标题】:Spring @Transactional not committing recordsSpring @Transactional 不提交记录
【发布时间】:2015-01-30 18:00:51
【问题描述】:

我使用 Spring 和 Hibernate。我正在使用以下配置。当我尝试通过 Spring 事务保存时,记录永远不会提交。

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

    <context:component-scan base-package="com.wpt.controllers,com.wpt.dao" />

    <mvc:annotation-driven />

    <mvc:default-servlet-handler />

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

    <bean id="wptDatasource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/wp" />
        <property name="username" value="user" />
        <property name="password" value="pass" />
    </bean>
    <bean id="hibernate4AnnotatedSessionFactory"
            class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
            <property name="dataSource" ref="wptDatasource" />
            <property name="packagesToScan" value="com.wpt.models" />
            <property name="hibernateProperties">
                <props>
                    <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                    <prop key="hibernate.current_session_context_class">thread</prop>
                    <prop key="hibernate.show_sql">false</prop>
                </props>
            </property>
        </bean>

        <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"
            p:sessionFactory-ref="hibernate4AnnotatedSessionFactory">
        </bean></beans>

我的控制器类

@Transactional
@RequestMapping(...)
public String saveRecords(@ModelAttribute("orderObj") Order order){
  for(Item item : order.getItems()){
    itemDAO.save(item);
  }
  return "saveSuccess";
}

MyDAO类

public void save(Item item){
  session = sf.openSession();
  session.save(item);
  session.close();
}

上面的@Transactional 配置没有提交记录。但是,如果我从 spring 控制器中删除 @Transactional 并使用 Hibernate 事务,如下所示,记录会提交。

public void save(Item item){
  session = sf.openSession();
  Transaction tx = session.beginTransaction();
  session.persist(item);
  tx.commit();
  session.close();
}

这个类提交记录。 我浏览了一些论坛,并提到@Transactional 将负责提交记录。我在这里犯了什么错误?有人可以帮忙吗?

提前致谢。

【问题讨论】:

  • 你有spring配置文件吗?
  • 是的,我在问题本身中给出了 sessionfactory 和 transactionmanagement bean。我需要把整个文件放在这里吗?
  • 我的意思是引入一个带有事务方法的单独组件,控制器委托给它以执行业务逻辑。将@Transactional 放在控制器上可能会导致问题,因为它引入了代理,并且控制器可以获得其他事物的代理,并且可能导致混乱。 here's an example
  • 尝试将 放入您的配置文件中。这是使用注释启用事务所必需的。此外,您还必须为 tx 添加架构位置
  • 首先,你没有&lt;tx:annotation-driven /&gt;,这基本上使@Transactional 无用。接下来,您正在搞乱hibernate.current_session_context_class,在您的情况下,这会破坏正确的 Spring 集成。删除它。另一件事恕我直言,让您的 Web 层事务性不是一件好事(这就是您现在所做的)。创建服务并使其具有事务性。

标签: spring hibernate spring-transactions


【解决方案1】:

在我将 &lt;tx:annotation-driven /&gt; 注释添加到我的配置 xml 并从 hibernateSessionFactory bean 中删除 hibernate.current_session_context_class 之后,它起作用了。鉴于以下更改。

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

<context:component-scan base-package="com.wpt.controllers,com.wpt.dao" />

<mvc:annotation-driven />

<mvc:default-servlet-handler />

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

<bean id="wptDatasource" class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://localhost:3306/wp" />
    <property name="username" value="user" />
    <property name="password" value="pass" />
</bean>
<bean id="hibernate4AnnotatedSessionFactory"
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="wptDatasource" />
        <property name="packagesToScan" value="com.wpt.models" />
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                <!-- <prop key="hibernate.current_session_context_class">thread</prop> -->
                <prop key="hibernate.show_sql">false</prop>
            </props>
        </property>
    </bean>

    <tx:annotation-driven transaction-manager="transactionManager"/>
    <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"
        p:sessionFactory-ref="hibernate4AnnotatedSessionFactory">
    </bean>
</beans>

然后我在我的所有服务方法中添加了org.springframework.transaction.annotation.Transactional 注释并从我的 DAO 类中删除了所有事务。

public void save(Item item){
  //session = sf.openSession();
  session.save(item);
  //session.close();
}

感谢大家的帮助。

【讨论】:

  • 你不应该自己打开会话,也不要关闭它们。你还没有使用 spring,使用 sf.getCurrentSession().save(item) 而不是你现在拥有的。
猜你喜欢
  • 1970-01-01
  • 2021-03-26
  • 1970-01-01
  • 2013-04-24
  • 2017-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-12
相关资源
最近更新 更多