Spring事务回滚失败

发布于 2022-09-11 15:00:42 字数 5448 浏览 15 评论 0

我在Service层里面调用两个Dao层的方法。一个方法用于储存一行Investor数据,一个方法用于储存和有Investor主键的Address数据。service层方法如下,注意Investor继承Person,放在同一个数据库表里面。

@Service
public class ServiceImpl implements PortfolioService {

    @Autowired
    private PersonDao personDao;//Dao层接口

    @Transactional(rollbackFor = { Throwable.class })
    public void addInvestor(String personCode, String firstName, String lastName, String country, String state,
            String street) {
        Investor p = new Investor(personCode,firstName,lastName);
        int personId = personDao.addPerson(p);//第一个方法添加investor,方法返回该行数据自动生成的主键
        Address ad = new Address(street,state, country);
        personDao.addAddress(ad,personId);//第二个方法添加address,前面生成的personId会成为Address属性,因为Address对应一个investor
    }
}

我必须保证这两个方法的原子性,如果addAddress出现了问题,addPerson必须回滚。但是我的方法始终没有达到回滚的效果。我成功地插入一行person数据,addAddress方法出错,addPerson方法却没有回滚。

以下是相关的xml配置文件和代码
Spring-Hibernate.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
      http://www.springframework.org/schema/context
      http://www.springframework.org/schema/context/spring-context.xsd
      http://www.springframework.org/schema/mvc
      http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
      http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
    
    <context:component-scan base-package="dao,pojo,service,pojoView"/>
    
     <!-- 引入property配置文件 -->  
    <context:property-placeholder location="jdbc.properties"/>  
    <!-- 配置数据源 -->
    <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${jdbc.mysql.driverClassName}" />
        <property name="url" value="${jdbc.mysql.url}" />
        <property name="username" value="${jdbc.mysql.username}" />
        <property name="password" value="${jdbc.mysql.password}" />
    </bean>

    <!--  配置hibernate SessionFactory with a spring plug in -->
    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        
        <!-- hibernate自动扫描 实体类-->
        <property name="packagesToScan">
            <list>
                <value>pojo</value>
                <value>pojoView</value>
            </list>
        </property>
        
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">${jdbc.mysql.dialect}</prop>
                <prop key="hibernate.hbm2ddl.auto">${jdbc.hibernate.hbm2ddl.auto}</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hiberante.format_sql">true</prop>
            </props>
        </property>
        
        <property name="configLocations">
            <list>
                <value>classpath*:hibernate.cfg.xml</value>                
            </list>
        </property>
    </bean>


    <!-- 事务管理器 -->
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate5.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"></property>
    </bean>
    
    <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />
    

下面是我在UnitTest方法里面调用Service层的方法。
PersonTest.java

public class PersonTest extends BaseTest {
    
    @Autowired
    private PortfolioService ps;

    
    public PersonTest() {
        System.out.println("PersonTest构造方法");
    }
    

    @Test
    public void test8() {
        ps.addInvestor("kk5", "m4", "chrow", "Cua", "Nebska", "D stret");
    }

BaseTest.java

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath*:Spring-Hibernate.xml")
public class BaseTest {
    
    @Before
    public void init() {
        System.out.println("initializing");
    }

}

PersonDaoImpl.java

@Repository
public class PersonDaoImpl implements PersonDao {

    @Autowired
    private SessionFactory sessionFactory;

    public void addAddress(Address ad,int personId) {
        Session session = sessionFactory.openSession();
        //ad.setPersonId(personId);
        session.save(ad);

        session.close();

    }

    public int addPerson(Person p) {
        Session session = sessionFactory.openSession();
        session.save(p);
        int personId = p.getPersonId();
        session.close();
        return personId;
    }



}

请大神指点一下这个为什么不能回滚,测试方法test8()没有报错,只是Investor的数据被存入了数据库,没有因为addAddress的异常而回滚。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

日记撕了你也走了 2022-09-18 15:00:42

你这是两个事务呀,openSession是开启一个新事物,如果你要保证ACID,所有操作必须在同一个事务中

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文