ChatGPT解决这个技术问题 Extra ChatGPT

注释@Transactional。如何回滚?

我成功地将这个注解用于一个 Dao 类。回滚适用于测试。

但现在我需要回滚真实代码,而不仅仅是测试。有用于测试的特殊注释。但是哪些注解是针对非测试代码的呢?对我来说这是一个很大的问题。我已经为此花了一天时间。官方文档不符合我的需求。

class MyClass { // this does not make rollback! And record appears in DB.
        EmployeeDaoInterface employeeDao;

        public MyClass() {
            ApplicationContext context = new ClassPathXmlApplicationContext(
                    new String[] { "HibernateDaoBeans.xml" });
            employeeDao = (IEmployeeDao) context.getBean("employeeDao");
         }

        @Transactional(rollbackFor={Exception.class})
    public void doInsert( Employee newEmp ) throws Exception {
        employeeDao.insertEmployee(newEmp);
        throw new RuntimeException();
    }
}

员工道是

@Transactional
public class EmployeeDao implements IEmployeeDao {
    private SessionFactory sessionFactory;

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public void insertEmployee(Employee emp) {
        sessionFactory.getCurrentSession().save(emp);
    }
}

这是一个注释工作良好的测试:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/HibernateDaoBeans.xml" })
@TransactionConfiguration(transactionManager = "txManager", defaultRollback = true)
@Transactional
public class EmployeeDaoTest {

    @Autowired
    EmployeeDaoInterface empDao;

    @Test
    public void insert_record() {
       ...
       assertTrue(empDao.insertEmployee(newEmp));
    }

HibernateDaoBeans.xml

   ...
<bean id="employeeDao" class="Hibernate.EmployeeDao">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>
    <tx:annotation-driven transaction-manager="txManager"/>

<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>
   ...

**是的,我回滚了交易。我刚刚为服务添加了 BEAN...然后注释 @Transactional 开始工作:-) **

<bean id="service" class="main.MyClass">
    <property name="employeeDao" ref="employeeDao" />
</bean>

谢谢大家,俄罗斯不会忘记你的!


T
Tomasz Nurkiewicz

只需从标记为 @Transactional 的方法中抛出任何 RuntimeException

默认情况下,所有 RuntimeException 的回滚事务都不会,而检查的异常则不会。这是 EJB 的遗产。您可以使用 rollbackFor()noRollbackFor() 注释参数进行配置:

@Transactional(rollbackFor=Exception.class)

这将在抛出任何异常后回滚事务。


我尝试过这个。这没用!我不直接在 Dao 对象中讲述回滚操作,这可能会起作用。我讲述了另一个使用 @Transactional 的 Dao 方法调用序列的对象。我尝试为我的类添加相同的注释,调用这个 Dao。但它在这里不起作用。
它真的是这样工作的:-)。如果您有一个服务调用多个 DAO,则该服务还需要有一个 @Transactional 注释。否则,每个 DAO 调用都会在您在服务中引发异常之前启动并提交新事务。底线是:异常必须离开(转义)标记为 @Transactional 的方法。
查看第一篇文章中添加的代码。我有部分代码。执行后我在数据库中有记录。 => 回滚还不起作用。
从 DAO 抛出异常是否也不会回滚事务?您是否在 Spring 上下文中配置了 org.springframework.orm.hibernate3.HibernateTransactionManager?如果启用 org.springframework.transaction 记录器,它会显示什么有趣的东西吗?
如果您使用 Spring Boot 并让它自动配置 DataSource,它将使用 HikariDataSource,默认情况下自动提交设置为 true。您需要将其设置为 false:hikariDataSource.setAutoCommit(false);在配置 DataSourceTransactionManager bean 时,我在 @Configuration 类中进行了此更改。
S
Stefan K.

或以编程方式

TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

是的。因为有时您需要回滚而不抛出错误。
你是救生员。
这是调用回滚 imo 的更合适的方法,理想情况下,您不想为已知或受控条件抛出异常。
有时它不起作用。例如,就我而言,我有一个事务性服务和非事务性存储库。我从服务调用存储库,因此,它应该参与服务打开的事务。但是,如果我从我的非事务性存储库中调用您的代码,它会抛出 NoTransactionException,尽管事实上存在事务。
您想在“非事务性存储库”中回滚哪个事务?
A
Alex Barnes

您可以从要回滚的方法中抛出未经检查的异常。这将被 spring 检测到,并且您的事务将被标记为仅回滚。

我假设你在这里使用 Spring。我假设您在测试中引用的注释是基于弹簧测试的注释。

向 Spring Framework 的事务基础结构指示事务的工作要回滚的推荐方法是从当前在事务上下文中执行的代码中抛出异常。

并注意:

请注意,Spring 框架的事务基础结构代码默认情况下只会在运行时、未经检查的异常情况下将事务标记为回滚;也就是说,当抛出的异常是 RuntimeException 的实例或子类时。


R
Roberto Rodriguez

对我来说 rollbackFor 是不够的,所以我不得不把它放进去,它按预期工作:

@Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)

我希望它有帮助:-)


不,它根本没有帮助 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); 下面你帮助