事务中的Spring编程事务

事务中的Spring编程事务,spring,transactions,nested,Spring,Transactions,Nested,我写了下面的代码做下面的活动 我使用Spring类创建了一个事务。 插入一行。 创建其他事务。 插入另一行。 提交的外部事务。 回滚内部事务 TransactionStatus trxstsOuter= dsTrxMngr.getTransaction(null); jdbcTemplate.update("insert into kau_emp values(6,'xyz' )"); TransactionStatus trxstsInner= dsTrxMngr.getTra

我写了下面的代码做下面的活动 我使用Spring类创建了一个事务。 插入一行。 创建其他事务。 插入另一行。 提交的外部事务。 回滚内部事务

TransactionStatus trxstsOuter= dsTrxMngr.getTransaction(null);
    jdbcTemplate.update("insert into kau_emp values(6,'xyz' )");
    TransactionStatus trxstsInner= dsTrxMngr.getTransaction(null);
        jdbcTemplate.update("insert into kau_emp values(7,'pqr' )");

dsTrxMngr.commit(trxstsOuter);
System.out.println("trxstsOuter.isCompleted()" + trxstsOuter.isCompleted());
System.out.println("trxstsInner.isCompleted()" + trxstsInner.isCompleted());
dsTrxMngr.rollback(trxstsInner);
    System.out.println("trxstsInner.isCompleted()" + trxstsInner.isCompleted());
我注意到这两行都提交给DB!! 输出是

trxstsOuter.isCompleted()true
trxstsInner.isCompleted()false
trxstsInner.isCompleted()true
这是正确的行为吗? 在允许外部事务提交之前,是否应该首先提交/回滚内部事务?
如果提交了外部事务,内部事务的回滚是否会引发错误?

在您的示例中,transaction Propagation.REQUIRED用作默认值,并且所有逻辑事务都映射到单个物理事务

当需要传播设置时,逻辑 事务作用域是为设置所基于的每个方法创建的 应用每个这样的逻辑事务范围都可以确定 使用外部事务作用域单独回滚状态 逻辑上独立于内部事务范围。属于 当然,对于标准的传播行为,所有这些 作用域将映射到同一物理事务。那么 内部事务作用域中设置的仅回滚标记不会影响 外部事务按预期实际提交的机会 是的

因此,在您的示例中,两个逻辑事务映射到一个物理事务

TransactionStatus trxstsOuter= dsTrxMngr.getTransaction(null);
    jdbcTemplate.update("insert into kau_emp values(6,'xyz' )");
    TransactionStatus trxstsInner= dsTrxMngr.getTransaction(null);
        jdbcTemplate.update("insert into kau_emp values(7,'pqr' )");

dsTrxMngr.commit(trxstsOuter);
System.out.println("trxstsOuter.isCompleted()" + trxstsOuter.isCompleted());
System.out.println("trxstsInner.isCompleted()" + trxstsInner.isCompleted());
dsTrxMngr.rollback(trxstsInner);
    System.out.println("trxstsInner.isCompleted()" + trxstsInner.isCompleted());

请参见示例事务传播中的

。REQUIRED用作默认值,并且所有逻辑事务都映射到单个物理事务

当需要传播设置时,逻辑 事务作用域是为设置所基于的每个方法创建的 应用每个这样的逻辑事务范围都可以确定 使用外部事务作用域单独回滚状态 逻辑上独立于内部事务范围。属于 当然,对于标准的传播行为,所有这些 作用域将映射到同一物理事务。那么 内部事务作用域中设置的仅回滚标记不会影响 外部事务按预期实际提交的机会 是的

因此,在您的示例中,两个逻辑事务映射到一个物理事务

TransactionStatus trxstsOuter= dsTrxMngr.getTransaction(null);
    jdbcTemplate.update("insert into kau_emp values(6,'xyz' )");
    TransactionStatus trxstsInner= dsTrxMngr.getTransaction(null);
        jdbcTemplate.update("insert into kau_emp values(7,'pqr' )");

dsTrxMngr.commit(trxstsOuter);
System.out.println("trxstsOuter.isCompleted()" + trxstsOuter.isCompleted());
System.out.println("trxstsInner.isCompleted()" + trxstsInner.isCompleted());
dsTrxMngr.rollback(trxstsInner);
    System.out.println("trxstsInner.isCompleted()" + trxstsInner.isCompleted());

请参见当前代码中的

,第二个getTransaction调用是noop。此行为由名为PropagationBehavior的属性控制。默认的传播行为是propagation_REQUIRED,这意味着如果不存在新事务,则启动新事务,或者加入现有事务。这就是你的情况

如果将第二个事务的“传播行为”属性更改为“传播\u需要\u新建”-您将获得预期的行为。一旦提交/回滚内部事务,外部事务将被挂起并创建新事务。外部事务将自动恢复。我已经修改了您的代码以合并此行为,现在当您尝试在内部事务之前提交外部事务时,应该会出现异常。如果您修复了序列,那么提交将独立进行

TransactionStatus trxstsOuter= dsTrxMngr.getTransaction(null);
jdbcTemplate.update("insert into kau_emp values(6,'xyz' )");
    // start a new transaction.
    DefaultTransactionDefinition nestedTransDef = new DefaultTransactionDefinition();
    nestedTransDef.setPropagationBehavior(             
           TransactionDefinition.PROPAGATION_REQUIRES_NEW);
    TransactionStatus trxstsInner= dsTrxMngr.getTransaction(nestedTransDef);
     System.out.println("trxstsInner.isNewTransaction()"+ trxstsInner.isNewTransaction());  
        jdbcTemplate.update("insert into kau_emp values(7,'pqr' )");

dsTrxMngr.commit(trxstsOuter);
    System.out.println("trxstsOuter.isCompleted()" + trxstsOuter.isCompleted());
    System.out.println("trxstsInner.isCompleted()" + trxstsInner.isCompleted());
    dsTrxMngr.rollback(trxstsInner);
    System.out.println("trxstsInner.isCompleted()" + trxstsInner.isCompleted());

另一方面,您应该使用注释来管理事务——这是将事务合并到代码中的一种更干净/更好的方法。编程事务只适用于少数需要更多控制的情况。另外,在使用TransactionTemplate执行编程事务时,建议使用。在当前代码中,第二个getTransaction调用是noop。此行为由名为PropagationBehavior的属性控制。默认的传播行为是propagation_REQUIRED,这意味着如果不存在新事务,则启动新事务,或者加入现有事务。这就是你的情况

如果将第二个事务的“传播行为”属性更改为“传播\u需要\u新建”-您将获得预期的行为。一旦提交/回滚内部事务,外部事务将被挂起并创建新事务。外部事务将自动恢复。我已经修改了您的代码以合并此行为,现在当您尝试在内部事务之前提交外部事务时,应该会出现异常。如果您修复了序列,那么提交将独立进行

TransactionStatus trxstsOuter= dsTrxMngr.getTransaction(null);
jdbcTemplate.update("insert into kau_emp values(6,'xyz' )");
    // start a new transaction.
    DefaultTransactionDefinition nestedTransDef = new DefaultTransactionDefinition();
    nestedTransDef.setPropagationBehavior(             
           TransactionDefinition.PROPAGATION_REQUIRES_NEW);
    TransactionStatus trxstsInner= dsTrxMngr.getTransaction(nestedTransDef);
     System.out.println("trxstsInner.isNewTransaction()"+ trxstsInner.isNewTransaction());  
        jdbcTemplate.update("insert into kau_emp values(7,'pqr' )");

dsTrxMngr.commit(trxstsOuter);
    System.out.println("trxstsOuter.isCompleted()" + trxstsOuter.isCompleted());
    System.out.println("trxstsInner.isCompleted()" + trxstsInner.isCompleted());
    dsTrxMngr.rollback(trxstsInner);
    System.out.println("trxstsInner.isCompleted()" + trxstsInner.isCompleted());

另一方面,您应该使用注释来管理事务——这是将事务合并到代码中的一种更干净/更好的方法。编程事务只适用于少数需要更多控制的情况。此外,建议在使用TransactionTemplate执行编程事务时使用。

有许多与事务管理器相关的内容本地事务/容器管理/托管事务/自定义事务管理器、事务传播、逻辑事务/ph
物理事务、内部事务、数据库限制并非每个rdbms都支持托管事务等。因此,我敢发布任何答案:-这需要多年的学习,我不认为试错法是开始的方式:-事务与javadoc相同says@BorisTreukhov从调试中可以看出它们是不同的对象,从isCompleted的sysout中也可以看出它们是被处理的seperately@BorisTreukhov您说过嵌套事务不是每个rdbms都支持的。。。。我正在使用hsqldb。这可能是个问题吗?在大多数应用程序中,你只使用单一事务,嵌套的db事务是非常高级的东西,很少使用-如果可能的话,应该使用java实体对象作为状态。有很多事情与事务管理器Local transaction/container managed/managed transactions/custom transaction Manager、事务传播、,逻辑事务/物理事务、内部事务、数据库限制并非每个rdbms都支持托管事务。因此,我甚至敢发布任何答案:-这需要多年的学习,我不认为试错法是开始的方式:-事务与javadoc相同says@BorisTreukhov从调试中可以看出它们是不同的对象,从isCompleted的sysout中也可以看出它们是被处理的seperately@BorisTreukhov您说过嵌套事务不是每个rdbms都支持的。。。。我正在使用hsqldb。这可能是个问题吗?在大多数应用程序中,您只使用单个事务,嵌套的db事务是非常高级的东西,很少使用-您应该尽可能使用java实体对象作为状态。您是对的。创建trxstInner.isNewTransaction后,我打印了它。它印的是薄片。后来,我创建了带有传播的内部事务。在这种情况下,trxstInner.isNewTransaction为true,并且它不允许我在提交外部事务后回滚内部事务。内部事务中出现的插入未提交。您是对的。创建trxstInner.isNewTransaction后,我打印了它。它印的是薄片。后来,我创建了带有传播的内部事务。在这种情况下,trxstInner.isNewTransaction为true,并且它不允许我在提交外部事务后回滚内部事务。未提交在内部事务中进行的插入。我使用传播\u REQUIRES\u NEW创建了内部事务。在这种情况下,trxstInner.isNewTransaction为true,并且它不允许我在提交外部事务后回滚内部事务。内部事务中出现的插入未提交。我提到的上述代码不正确。您必须在外部事务之前提交/回滚内部事务。我原以为如果您以另一种方式进行操作,它会引发异常,但如果它正在提交外部事务,则它是一个bug,但不是一个关键问题,因为它不正确地使用了apiI创建的内部事务。在这种情况下,trxstInner.isNewTransaction为true,并且它不允许我在提交外部事务后回滚内部事务。内部事务中出现的插入未提交。我提到的上述代码不正确。您必须在外部事务之前提交/回滚内部事务。我原以为如果您以另一种方式进行操作,它会抛出异常,但如果它正在提交外部事务,则它是错误的,但不是关键的,因为它是api的错误使用