@Transactional(propagation = Propagation.REQUIRED)
public void persistEmployee() {
Employee employee = new Employee("Peter", "Washington DC");
entityManager.persist(employee);
try {
persistLineManager();
}
catch( Exception e ) {
// some task
}
}
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = RuntimeException.class)
public void persistLineManager() {
Employee lineManager = new Employee("John", "NYC");
entityManager.persist(lineManager);
if(lineManager != null) // intentionally! To trigger rollback
throw new RuntimeException("Rollback!");
}
根据Spring文档,当传播级别为required
时,两个方法将在同一事务中运行。在我的代码中,我有意抛出异常来触发回滚,但仍然保持了两个实体。但我认为这两项行动都应该取消。如果我的理解不正确,请更正,并让我知道回滚两个操作的正确方法。
PROPAGATION_REQUIRES_NEW:[来自spring Docs]
PROPAGATION_REQUIRES_NEW与PROPAGATION_REQUIRED不同,它为每个受影响的事务范围使用一个完全独立的事务。在这种情况下,基础物理事务是不同的,因此可以独立提交或回滚,外部事务不受内部事务回滚状态的影响。
现在,这个“任何来自外界的来电者都不会直接与你对话”是非常重要的。如果进行内部调用,就像在PersistEmployee
中调用PersistLineManager
一样,则不通过代理。您直接调用您的方法,而不是代理。因此,您的PersistLineManager
方法顶部的注释不会被读取。
因此,当PersistLineManager
抛出RuntimeException
时,调用方PersistEmployee
直接捕获异常,您可以直接进行捕获。由于没有代理,因此没有回滚,因为事务性代理没有捕获异常。
如果只执行此操作,将发生回滚:
@Transactional(propagation = Propagation.REQUIRED)
public void persistEmployee() {
Employee employee = new Employee("Peter", "Washington DC");
entityManager.persist(employee);
persistLineManager();
// Don't catch and the exception will be catched by the transaction proxy, which will rollback
}
public void persistLineManager() {
Employee lineManager = new Employee("John", "NYC");
entityManager.persist(lineManager);
if(lineManager != null) // intentionally! To trigger rollback
throw new RuntimeException("Rollback!");
}
class MyService {
// Have a field of type TransactionTemplate
private TransactionTemplate template;
// In the constructor, Spring will inject the correct bean
public MyService(PlatformTransactionManager transactionManager) {
template = new TransactionTemplate(transactionManager);
// Set this here if you always want this behaviour for your programmatic transaction
template.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
}
// Here you start your first transaction when arriving from the outside
@Transactional(propagation = Propagation.REQUIRED)
public void persistEmployee() {
Employee employee = new Employee("Peter", "Washington DC");
entityManager.persist(employee);
// Inner call
try {
persistLineManager();
} catch (RuntimeException e) {
// Do what you want
}
}
public void persistLineManager() {
// Here, ask to your transactionTemplate to execute your code.
template.execute(status -> {
Employee lineManager = new Employee("John", "NYC");
entityManager.persist(lineManager);
if(lineManager != null) // intentionally! To trigger rollback
throw new RuntimeException("Rollback!");
return null;
});
}
}
让我添加关于PROPAGATION_REQUIRED和propagation_requires_new之间区别的最后一部分:
Spring Transaction Propagation如何为Propagation_REQUIRED和Propagation_REQUIRED_NEW工作? 请提供有关类到类级别和方法到方法级别的传播的信息。 我还需要知道如何初始化/启动这些事务,并在当前事务完成时恢复以前的事务,以进行传播。 在需要传播和需要新传播的情况下使用单个事务时,事务将如何决定何时需要提交/回滚?
在下面的文章中说, 在此处输入链接描述 需要传播–支持当前交易;如果不存在,请创建一个新的。 下面是一个产品代码,然后是两个表的产品详细信息。 我的问题是什么时候会发生这种行为?我的意思是,当前交易怎么会结束?是在保存还是更新之后? 如果我们使用PROPAGATION_REQUIRED假设当前事务在插入产品后结束。然后一个新的事务来了,但是如果插入产品数量时出现任何故障,它只会回滚数量而不是输入的
问题内容: 我知道静态方法在类级别。因此,我知道我不需要创建实例来调用静态方法。但我也知道我可以将静态方法(如LIKE)称为实例方法。这是我感到困惑的地方,因为我期望从null对象调用静态方法(就像在调用实例方法中一样)。我真的很感谢一些解释,为什么我错了一个期望。 这是示例代码: 问题答案: 通过实例调用静态方法不需要实例存在。只要编译器能够确定变量的类型,它就可以在评估表达式并丢弃结果后静态进
问题内容: 注意:我知道该方法。 在下面的代码示例中,我不明白为什么在方法抛出,但不是在方法。 问题答案: 原因如下:正如中所说: 此类的迭代器和方法返回的迭代器是快速失败的:如果在创建迭代器后的任何时间以任何方式对列表进行结构修改,除非通过迭代器自己的remove或add方法,否则迭代器将抛出。 该检查是在迭代器的方法中完成的(如你在stacktrace中所看到的)。但是,next()只有在传递
在以下代码方法中,更新正确的sql,但sql有一些问题,但是,当我调用doService()时,它必须将更新提交到DB,即使doService 2()有sql异常,因为doService 2()有一个新的传播类型,但是当我取消这个更新时,不会提交DB。。 正如你们的建议,以以下方式进行测试,但仍然面临相同的问题。这里i在一个单独的类中,但即使仍然存在与上述相同的问题
我正在尝试处理用户的Backspace按键。我有2个处理程序绑定到一个输入元素。由于无法在onChange事件处理程序中检测按键,因此我必须在onKeyDown中进行。我想在按下backspace时停止onChange事件的传播(并在onKeyDown事件处理程序中处理)。有什么想法如何实现这一点?谢谢!