简体   繁体   English

Spring @Transactional - 隔离、传播

[英]Spring @Transactional - isolation, propagation

Can someone explain what isolation & propagation parameters are for in the @Transactional annotation via real-world example?有人可以通过实际示例解释@Transactional注释中的隔离传播参数是什么吗?

Basically when and why I should choose to change their default values.基本上什么时候以及为什么我应该选择更改它们的默认值。

Good question, although not a trivial one to answer.好问题,虽然不是一个微不足道的回答。

Propagation 传播

Defines how transactions relate to each other.定义事务如何相互关联。 Common options:常用选项:

  • REQUIRED : Code will always run in a transaction. REQUIRED :代码将始终在事务中运行。 Creates a new transaction or reuses one if available.创建一个新事务或重用一个(如果可用)。
  • REQUIRES_NEW : Code will always run in a new transaction. REQUIRES_NEW :代码将始终在新事务中运行。 Suspends the current transaction if one exists.如果存在,则暂停当前事务。

The default value for @Transactional is REQUIRED , and this is often what you want. @Transactional的默认值是REQUIRED ,这通常是您想要的。

Isolation 隔离

Defines the data contract between transactions.定义事务之间的数据契约。

  • ISOLATION_READ_UNCOMMITTED : Allows dirty reads. ISOLATION_READ_UNCOMMITTED :允许脏读。
  • ISOLATION_READ_COMMITTED : Does not allow dirty reads. ISOLATION_READ_COMMITTED :不允许脏读。
  • ISOLATION_REPEATABLE_READ : If a row is read twice in the same transaction, the result will always be the same. ISOLATION_REPEATABLE_READ :如果在同一个事务中两次读取一行,结果将始终相同。
  • ISOLATION_SERIALIZABLE : Performs all transactions in a sequence. ISOLATION_SERIALIZABLE :按顺序执行所有事务。

The different levels have different performance characteristics in a multi-threaded application.在多线程应用程序中,不同级别具有不同的性能特征。 I think if you understand the dirty reads concept you will be able to select a good option.我认为如果您了解脏读概念,您将能够选择一个好的选项。

Defaults may vary between difference databases.不同数据库之间的默认值可能会有所不同。 As an example, for MariaDB it is REPEATABLE READ .例如,对于MariaDB,它是REPEATABLE READ


Example of when a dirty read can occur:可能发生脏读的示例:

  thread 1   thread 2      
      |         |
    write(x)    |
      |         |
      |        read(x)
      |         |
    rollback    |
      v         v 
           value (x) is now dirty (incorrect)

So a sane default (if such can be claimed) could be ISOLATION_READ_COMMITTED , which only lets you read values which have already been committed by other running transactions, in combination with a propagation level of REQUIRED .因此,合理的默认值(如果可以声明)可以是ISOLATION_READ_COMMITTED ,它只允许您读取其他正在运行的事务已经提交的值,并结合传播级别REQUIRED Then you can work from there if your application has other needs.如果您的应用程序有其他需求,您可以从那里开始工作。


A practical example of where a new transaction will always be created when entering the provideService routine and completed when leaving:一个在进入provideService例程时总是创建新事务并在离开时完成的实际示例:

public class FooService {
    private Repository repo1;
    private Repository repo2;

    @Transactional(propagation=Propagation.REQUIRES_NEW)
    public void provideService() {
        repo1.retrieveFoo();
        repo2.retrieveFoo();
    }
}

Had we instead used REQUIRED , the transaction would remain open if the transaction was already open when entering the routine.如果我们改为使用REQUIRED ,则如果在进入例程时事务已经打开,则事务将保持打开状态。 Note also that the result of a rollback could be different as several executions could take part in the same transaction.另请注意, rollback的结果可能不同,因为多个执行可能参与同一事务。


We can easily verify the behaviour with a test and see how results differ with propagation levels:我们可以通过测试轻松验证行为,并查看结果与传播级别有何不同:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:/fooService.xml")
public class FooServiceTests {

    private @Autowired TransactionManager transactionManager;
    private @Autowired FooService fooService;

    @Test
    public void testProvideService() {
        TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
        fooService.provideService();
        transactionManager.rollback(status);
        // assert repository values are unchanged ... 
}

With a propagation level of传播水平为

  • REQUIRES_NEW : we would expect fooService.provideService() was NOT rolled back since it created it's own sub-transaction. REQUIRES_NEW :我们希望fooService.provideService()不会回滚,因为它创建了自己的子事务。

  • REQUIRED : we would expect everything was rolled back and the backing store was unchanged. REQUIRED :我们希望一切都回滚并且后备存储保持不变。

PROPAGATION_REQUIRED = 0 ; PROPAGATION_REQUIRED = 0 ; If DataSourceTransactionObject T1 is already started for Method M1.如果 DataSourceTransactionObject T1 已经为方法 M1 启动。 If for another Method M2 Transaction object is required, no new Transaction object is created.如果需要另一个 Method M2 Transaction 对象,则不会创建新的 Transaction 对象。 Same object T1 is used for M2.相同的对象 T1 用于 M2。

PROPAGATION_MANDATORY = 2 ; PROPAGATION_MANDATORY = 2 ; method must run within a transaction.方法必须在事务中运行。 If no existing transaction is in progress, an exception will be thrown.如果没有正在进行的现有事务,则会抛出异常。

PROPAGATION_REQUIRES_NEW = 3 ; PROPAGATION_REQUIRES_NEW = 3 ; If DataSourceTransactionObject T1 is already started for Method M1 and it is in progress (executing method M1).如果 DataSourceTransactionObject T1 已经为方法 M1 启动并且正在进行中(正在执行方法 M1)。 If another method M2 start executing then T1 is suspended for the duration of method M2 with new DataSourceTransactionObject T2 for M2.如果另一个方法 M2 开始执行,则 T1 将在方法 M2 的持续时间内挂起,并为 M2 提供新的 DataSourceTransactionObject T2。 M2 run within its own transaction context. M2 在它自己的事务上下文中运行。

PROPAGATION_NOT_SUPPORTED = 4 ; PROPAGATION_NOT_SUPPORTED = 4 ; If DataSourceTransactionObject T1 is already started for Method M1.如果 DataSourceTransactionObject T1 已经为方法 M1 启动。 If another method M2 is run concurrently.如果另一个方法 M2 并发运行。 Then M2 should not run within transaction context.那么 M2 不应在事务上下文中运行。 T1 is suspended till M2 is finished. T1 暂停,直到 M2 完成。

PROPAGATION_NEVER = 5 ; PROPAGATION_NEVER = 5 ; None of the methods run in transaction context.没有任何方法在事务上下文中运行。


An isolation level: It is about how much a transaction may be impacted by the activities of other concurrent transactions.隔离级别:它是关于一个事务可能受到其他并发事务活动影响的程度。 It a supports consistency leaving the data across many tables in a consistent state.它支持一致性,使跨多个表的数据处于一致状态。 It involves locking rows and/or tables in a database.它涉及锁定数据库中的行和/或表。

The problem with multiple transaction多笔交易的问题

Scenario 1 .情景1 If T1 transaction reads data from table A1 that was written by another concurrent transaction T2.如果 T1 事务从另一个并发事务 T2 写入的表 A1 中读取数据。 If on the way T2 is rollback, the data obtained by T1 is invalid one.如果途中T2回滚,则T1获取的数据为无效数据。 Eg a=2 is original data.例如a=2 是原始数据。 If T1 read a=1 that was written by T2.如果 T1 读取了 T2 写入的 a=1。 If T2 rollback then a=1 will be rollback to a=2 in DB.如果 T2 回滚,那么 a=1 将回滚到 DB 中的 a=2。 But, now, T1 has a=1 but in DB table it is changed to a=2.但是,现在,T1 有 a=1,但在 DB 表中它更改为 a=2。

Scenario2 .场景2 If T1 transaction reads data from table A1.如果 T1 事务从表 A1 读取数据。 If another concurrent transaction (T2) update data on table A1.如果另一个并发事务(T2)更新表 A1 上的数据。 Then the data that T1 has read is different from table A1.那么T1读到的数据就和表A1不一样了。 Because T2 has updated the data on table A1.因为 T2 已经更新了表 A1 上的数据。 Eg if T1 read a=1 and T2 updated a=2.例如,如果 T1 读取 a=1 并且 T2 更新 a=2。 Then a!=b.那么 a!=b。

Scenario 3 .场景3 If T1 transaction reads data from table A1 with certain number of rows.如果 T1 事务从具有一定行数的表 A1 中读取数据。 If another concurrent transaction (T2) inserts more rows on table A1.如果另一个并发事务 (T2) 在表 A1 上插入更多行。 The number of rows read by T1 is different from rows on table A1. T1 读取的行数与表 A1 上的行数不同。

Scenario 1 is called Dirty reads.场景 1 称为脏读。

Scenario 2 is called Non-repeatable reads.场景 2 称为不可重复读取。

Scenario 3 is called Phantom reads.场景 3 称为幻读。

So, isolation level is the extend to which Scenario 1, Scenario 2, Scenario 3 can be prevented.因此,隔离级别是可以防止场景 1、场景 2、场景 3的扩展。 You can obtain complete isolation level by implementing locking.您可以通过实施锁定来获得完整的隔离级别。 That is preventing concurrent reads and writes to the same data from occurring.这阻止了对相同数据的并发读取和写入。 But it affects performance.但是会影响性能。 The level of isolation depends upon application to application how much isolation is required.隔离级别取决于应用程序之间需要多少隔离。

ISOLATION_READ_UNCOMMITTED : Allows to read changes that haven't yet been committed. ISOLATION_READ_UNCOMMITTED :允许读取尚未提交的更改。 It suffer from Scenario 1, Scenario 2, Scenario 3.它受到场景 1、场景 2、场景 3 的影响。

ISOLATION_READ_COMMITTED : Allows reads from concurrent transactions that have been committed. ISOLATION_READ_COMMITTED :允许从已提交的并发事务中读取。 It may suffer from Scenario 2 and Scenario 3. Because other transactions may be updating the data.它可能会受到场景 2 和场景 3 的影响。因为其他事务可能正在更新数据。

ISOLATION_REPEATABLE_READ : Multiple reads of the same field will yield the same results untill it is changed by itself. ISOLATION_REPEATABLE_READ :同一字段的多次读取将产生相同的结果,直到它自己更改为止。 It may suffer from Scenario 3. Because other transactions may be inserting the data.它可能会受到场景 3 的影响。因为其他事务可能正在插入数据。

ISOLATION_SERIALIZABLE : Scenario 1, Scenario 2, Scenario 3 never happen. ISOLATION_SERIALIZABLE :场景 1、场景 2、场景 3 永远不会发生。 It is complete isolation.这是完全隔离。 It involves full locking.它涉及完全锁定。 It affects performace because of locking.由于锁定,它会影响性能。

You can test using:您可以使用以下方法进行测试:

public class TransactionBehaviour {
   // set is either using xml Or annotation
    DataSourceTransactionManager manager=new DataSourceTransactionManager();
    SimpleTransactionStatus status=new SimpleTransactionStatus();
   ;
  
    
    public void beginTransaction()
    {
        DefaultTransactionDefinition Def = new DefaultTransactionDefinition();
        // overwrite default PROPAGATION_REQUIRED and ISOLATION_DEFAULT
        // set is either using xml Or annotation
        manager.setPropagationBehavior(XX);
        manager.setIsolationLevelName(XX);
       
        status = manager.getTransaction(Def);
    
    }

    public void commitTransaction()
    {
       
      
            if(status.isCompleted()){
                manager.commit(status);
        } 
    }

    public void rollbackTransaction()
    {
       
            if(!status.isCompleted()){
                manager.rollback(status);
        }
    }
    Main method{
        beginTransaction()
        M1();
        If error(){
            rollbackTransaction()
        }
         commitTransaction();
    }
   
}

You can debug and see the result with different values for isolation and propagation.您可以使用不同的隔离和传播值调试并查看结果。

Enough explanation about each parameter is given by other answers;其他答案对每个参数给出了足够的解释; However you asked for a real world example, here is the one that clarifies the purpose of different propagation options:但是,您要求提供一个真实世界的示例,以下是阐明不同传播选项目的的示例:

Suppose you're in charge of implementing a signup service in which a confirmation e-mail is sent to the user. 假设您负责实施注册服务,在该服务中向用户发送确认电子邮件。 You come up with two service objects, one for enrolling the user and one for sending e-mails, which the latter is called inside the first one. 您提出了两个服务对象,一个用于注册用户,一个用于发送电子邮件,后者在第一个内部调用。 For example something like this: 例如这样的事情:

/* User DAO */
@Transactional(Propagation=MANDATORY)
class UserDAO{
 // some CRUD methods
}

You may have noticed that the second service is of propagation type REQUIRES_NEW and moreover chances are it throws an exception (SMTP server down ,invalid e-mail or other reasons).You probably don't want the whole process to roll-back, like removing the user information from database or other things;您可能已经注意到,第二个服务的传播类型为REQUIRES_NEW ,而且它可能会引发异常(SMTP 服务器关闭、电子邮件无效或其他原因)。您可能不希望整个过程回滚,例如从数据库或其他东西中删除用户信息; therefore you call the second service in a separate transaction.因此,您在单独的事务中调用第二个服务。

Back to our example, this time you are concerned about the database security, so you define your DAO classes this way: 回到我们的例子,这次你关心数据库安全,所以你这样定义你的 DAO 类:

 /* User DAO */ @Transactional(Propagation=MANDATORY) class UserDAO{ // some CRUD methods }

Meaning that whenever a DAO object, and hence a potential access to db, is created, we need to reassure that the call was made from inside one of our services, implying that a live transaction should exist;这意味着无论何时创建 DAO 对象,从而创建对 db 的潜在访问,我们都需要确保调用是从我们的一个服务内部进行的,这意味着应该存在实时事务; otherwise an exception occurs.Therefore the propagation is of type MANDATORY .否则会发生异常。因此传播是MANDATORY类型。

Isolation level defines how the changes made to some data repository by one transaction affect other simultaneous concurrent transactions, and also how and when that changed data becomes available to other transactions.隔离级别定义了一个事务对某个数据存储库所做的更改如何影响其他同时并发的事务,以及更改的数据如何以及何时可供其他事务使用。 When we define a transaction using the Spring framework we are also able to configure in which isolation level that same transaction will be executed.当我们使用 Spring 框架定义事务时,我们还可以配置将在哪个隔离级别执行同一事务。

@Transactional(isolation=Isolation.READ_COMMITTED)
public void someTransactionalMethod(Object obj) {

}

READ_UNCOMMITTED isolation level states that a transaction may read data that is still uncommitted by other transactions. READ_UNCOMMITTED 隔离级别表明一个事务可以读取其他事务仍未提交的数据。

READ_COMMITTED isolation level states that a transaction can't read data that is not yet committed by other transactions. READ_COMMITTED 隔离级别表明事务无法读取其他事务尚未提交的数据。

REPEATABLE_READ isolation level states that if a transaction reads one record from the database multiple times the result of all those reading operations must always be the same. REPEATABLE_READ 隔离级别规定,如果一个事务多次从数据库读取一条记录,则所有这些读取操作的结果必须始终相同。

SERIALIZABLE isolation level is the most restrictive of all isolation levels. SERIALIZABLE 隔离级别是所有隔离级别中限制性最强的。 Transactions are executed with locking at all levels (read, range and write locking) so they appear as if they were executed in a serialized way.事务在所有级别(读取、范围和写入锁定)都使用锁定执行,因此它们看起来好像是以序列化方式执行的。

Propagation is the ability to decide how the business methods should be encapsulated in both logical or physical transactions.传播是决定业务方法应该如何封装在逻辑或物理事务中的能力。

Spring REQUIRED behavior means that the same transaction will be used if there is an already opened transaction in the current bean method execution context. Spring REQUIRED 行为意味着如果当前 bean 方法执行上下文中存在已打开的事务,则将使用相同的事务。

REQUIRES_NEW behavior means that a new physical transaction will always be created by the container. REQUIRES_NEW 行为意味着容器将始终创建新的物理事务。

The NESTED behavior makes nested Spring transactions to use the same physical transaction but sets savepoints between nested invocations so inner transactions may also rollback independently of outer transactions. NESTED 行为使嵌套的 Spring 事务使用相同的物理事务,但在嵌套调用之间设置保存点,因此内部事务也可以独立于外部事务回滚。

The MANDATORY behavior states that an existing opened transaction must already exist. MANDATORY 行为表明现有的已打开事务必须已经存在。 If not an exception will be thrown by the container.如果不是,容器将抛出异常。

The NEVER behavior states that an existing opened transaction must not already exist. NEVER 行为表明现有的已打开事务必须不存在。 If a transaction exists an exception will be thrown by the container.如果存在事务,容器将抛出异常。

The NOT_SUPPORTED behavior will execute outside of the scope of any transaction. NOT_SUPPORTED 行为将在任何事务的范围之外执行。 If an opened transaction already exists it will be paused.如果一个打开的事务已经存在,它将被暂停。

The SUPPORTS behavior will execute in the scope of a transaction if an opened transaction already exists.如果打开的事务已存在,则 SUPPORTS 行为将在事务范围内执行。 If there isn't an already opened transaction the method will execute anyway but in a non-transactional way.如果没有已经打开的事务,该方法无论如何都会执行,但以非事务方式执行。

A Transaction represents a unit of work with a database.一个事务代表一个数据库的工作单元。 Transaction behaviour in multiple service having their own txns(or no txn) is known as Transaction propagation .具有自己的 txns(或没有 txn)的多个服务中的事务行为被称为事务传播 Transaction Isolation defines the database state when two transactions concurrently act on the same database entity.当两个事务同时作用于同一个数据库实体时,事务隔离定义了数据库状态。

In spring TransactionDefinition interface that defines Spring-compliant transaction properties.在定义符合 Spring 的事务属性的 spring TransactionDefinition接口中。 @Transactional annotation describes transaction attributes on a method or class. @Transactional注释描述了方法或类上的事务属性。

@Autowired
private TestDAO testDAO;

@Transactional(propagation=TransactionDefinition.PROPAGATION_REQUIRED,isolation=TransactionDefinition.ISOLATION_READ_UNCOMMITTED)
public void someTransactionalMethod(User user) {

  // Interact with testDAO

}

Propagation (Reproduction) : is uses for inter transaction relation.传播(复制):用于事务间关系。 (analogous to java inter thread communication) (类似于java线程间通信)

+-------+---------------------------+------------------------------------------------------------------------------------------------------+
| value |        Propagation        |                                             Description                                              |
+-------+---------------------------+------------------------------------------------------------------------------------------------------+
|    -1 | TIMEOUT_DEFAULT           | Use the default timeout of the underlying transaction system, or none if timeouts are not supported. |
|     0 | PROPAGATION_REQUIRED      | Support a current transaction; create a new one if none exists.                                      |
|     1 | PROPAGATION_SUPPORTS      | Support a current transaction; execute non-transactionally if none exists.                           |
|     2 | PROPAGATION_MANDATORY     | Support a current transaction; throw an exception if no current transaction exists.                  |
|     3 | PROPAGATION_REQUIRES_NEW  | Create a new transaction, suspending the current transaction if one exists.                          |
|     4 | PROPAGATION_NOT_SUPPORTED | Do not support a current transaction; rather always execute non-transactionally.                     |
|     5 | PROPAGATION_NEVER         | Do not support a current transaction; throw an exception if a current transaction exists.            |
|     6 | PROPAGATION_NESTED        | Execute within a nested transaction if a current transaction exists.                                 |
+-------+---------------------------+------------------------------------------------------------------------------------------------------+

Isolation : Isolation is one of the ACID (Atomicity, Consistency, Isolation, Durability) properties of database transactions.隔离:隔离是数据库事务的 ACID(原子性、一致性、隔离性、持久性)属性之一。 Isolation determines how transaction integrity is visible to other users and systems.隔离确定事务完整性如何对其他用户和系统可见。 It uses for resource locking ie concurrency control, make sure that only one transaction can access the resource at a given point.它用于资源锁定,即并发控制,确保在给定点只有一个事务可以访问资源。

Locking perception: isolation level determines the duration that locks are held.锁定感知:隔离级别决定了持有锁的持续时间。

+---------------------------+-------------------+-------------+-------------+------------------------+
| Isolation Level Mode      |  Read             |   Insert    |   Update    |       Lock Scope       |
+---------------------------+-------------------+-------------+-------------+------------------------+
| READ_UNCOMMITTED          |  uncommitted data | Allowed     | Allowed     | No Lock                |
| READ_COMMITTED (Default)  |   committed data  | Allowed     | Allowed     | Lock on Committed data |
| REPEATABLE_READ           |   committed data  | Allowed     | Not Allowed | Lock on block of table |
| SERIALIZABLE              |   committed data  | Not Allowed | Not Allowed | Lock on full table     |
+---------------------------+-------------------+-------------+-------------+------------------------+

Read perception: the following 3 kinds of major problems occurs:阅读感知:主要出现以下3种问题:

  • Dirty reads : reads uncommitted data from another tx(transaction).脏读:从另一个 tx(transaction) 读取未提交的数据。
  • Non-repeatable reads : reads committed UPDATES from another tx.不可重复读取:从另一个 tx 读取已提交的UPDATES
  • Phantom reads : reads committed INSERTS and/or DELETES from another tx幻读:从另一个 tx 读取已提交的INSERTS和/或DELETES

Isolation levels with different kinds of reads:具有不同类型读取的隔离级别:

+---------------------------+----------------+----------------------+----------------+
| Isolation Level Mode      |  Dirty reads   | Non-repeatable reads | Phantoms reads |
+---------------------------+----------------+----------------------+----------------+
| READ_UNCOMMITTED          | allows         | allows               | allows         |
| READ_COMMITTED (Default)  | prevents       | allows               | allows         |
| REPEATABLE_READ           | prevents       | prevents             | allows         |
| SERIALIZABLE              | prevents       | prevents             | prevents       |
+---------------------------+----------------+----------------------+----------------+

for examples 举些例子

You almost never want to use Read Uncommited since it's not really ACID compliant.您几乎从不想使用Read Uncommited因为它并不真正符合ACID Read Commmited is a good default starting place. Read Commmited是一个很好的默认起始位置。 Repeatable Read is probably only needed in reporting, rollup or aggregation scenarios.可能只在报告、汇总或聚合场景中需要可Repeatable Read Note that many DBs, postgres included don't actually support Repeatable Read, you have to use Serializable instead.请注意,许多数据库,包括 postgres 实际上并不支持可重复读取,您必须使用Serializable来代替。 Serializable is useful for things that you know have to happen completely independently of anything else; Serializable对于您知道必须完全独立于其他任何事情发生的事情很有用; think of it like synchronized in Java.把它想象成 Java 中的synchronized Serializable goes hand in hand with REQUIRES_NEW propagation.可序列化与REQUIRES_NEW传播REQUIRES_NEW

I use REQUIRES for all functions that run UPDATE or DELETE queries as well as "service" level functions.我将REQUIRES用于所有运行 UPDATE 或 DELETE 查询的函数以及“服务”级别的函数。 For DAO level functions that only run SELECTs, I use SUPPORTS which will participate in a TX if one is already started (ie being called from a service function).对于仅运行 SELECT 的 DAO 级别函数,我使用SUPPORTS ,如果已经启动(即从服务函数调用),它将参与 TX。

Transaction Isolation and Transaction Propagation although related but are clearly two very different concepts.事务隔离和事务传播虽然相关,但显然是两个截然不同的概念。 In both cases defaults are customized at client boundary component either by using Declarative transaction management or Programmatic transaction management .在这两种情况下,默认值都是通过使用声明式事务管理程序化事务管理在客户端边界组件中自定义的。 Details of each isolation levels and propagation attributes can be found in reference links below.每个隔离级别和传播属性的详细信息可以在下面的参考链接中找到。

Transaction Isolation 事务隔离

For given two or more running transactions/connections to a database, how and when are changes made by queries in one transaction impact/visible to the queries in a different transaction.对于给定的两个或多个正在运行的事务/数据库连接,一个事务中的查询所做的更改如何以及何时对不同事务中的查询产生影响/可见。 It also related to what kind of database record locking will be used to isolate changes in this transaction from other transactions and vice versa.它还涉及将使用哪种数据库记录锁定来隔离此事务中的更改与其他事务,反之亦然。 This is typically implemented by database/resource that is participating in transaction.这通常由参与事务的数据库/资源​​实现。

. .

Transaction Propagation 交易传播

In an enterprise application for any given request/processing there are many components that are involved to get the job done.在用于任何给定请求/处理的企业应用程序中,有许多组件需要完成工作。 Some of this components mark the boundaries (start/end) of a transaction that will be used in respective component and it's sub components.其中一些组件标记将在相应组件及其子组件中使用的事务的边界(开始/结束)。 For this transactional boundary of components, Transaction Propogation specifies if respective component will or will not participate in transaction and what happens if calling component already has or does not have a transaction already created/started.对于组件的这个事务边界,事务传播指定各个组件是否将参与事务,以及如果调用组件已经或没有已经创建/启动的事务会发生什么。 This is same as Java EE Transaction Attributes.这与 Java EE 事务属性相同。 This is typically implemented by the client transaction/connection manager.这通常由客户端事务/连接管理器实现。

Reference:参考:

I have run outerMethod , method_1 and method_2 with different propagation modes.我已经使用不同的传播模式运行了outerMethodmethod_1method_2

Below is the output for different propagation modes.以下是不同传播模式的输出。

Outer Method外法

    @Transactional
    @Override
    public void outerMethod() {
        customerProfileDAO.method_1();
        iWorkflowDetailDao.method_2();
    }

Method_1方法_1

    @Transactional(propagation=Propagation.MANDATORY)
    public void method_1() {
        Session session = null;
        try {
            session = getSession();
            Temp entity = new Temp(0l, "XXX");
            session.save(entity);
            System.out.println("Method - 1 Id "+entity.getId());
        } finally {
            if (session != null && session.isOpen()) {

            }
        }
    }

Method_2方法_2

    @Transactional()
    @Override
    public void method_2() {
        Session session = null;
        try {
            session = getSession();
            Temp entity = new Temp(0l, "CCC");
            session.save(entity);
            int i = 1/0;
            System.out.println("Method - 2 Id "+entity.getId());
        } finally {
            if (session != null && session.isOpen()) {

            }
        }
    }
    • OuterMethod - Without transaction OuterMethod - 没有交易
    • Method_1 - Propagation.MANDATORY) - Method_1 - 传播。强制性) -
    • Method_2 - Transaction annotation only Method_2 - 仅交易注释
    • Output: method_1 will throw exception that no existing transaction输出:method_1 将抛出异常,表示没有现有事务

    • OuterMethod - Without transaction OuterMethod - 没有交易
    • Method_1 - Transaction annotation only Method_1 - 仅交易注释
    • Method_2 - Propagation.MANDATORY) Method_2 - 传播。强制性)
    • Output: method_2 will throw exception that no existing transaction输出:method_2 将抛出异常,即没有现有事务
    • Output: method_1 will persist record in database.输出:method_1 将在数据库中持久化记录。

    • OuterMethod - With transaction OuterMethod - 有事务
    • Method_1 - Transaction annotation only Method_1 - 仅交易注释
    • Method_2 - Propagation.MANDATORY) Method_2 - 传播。强制性)
    • Output: method_2 will persist record in database.输出:method_2 将记录在数据库中。
    • Output: method_1 will persist record in database.输出:method_1 将在数据库中持久化记录。 -- Here Main Outer existing transaction used for both method 1 and 2 -- 这里是用于方法 1 和方法 2 的 Main Outer 现有事务

    • OuterMethod - With transaction OuterMethod - 有事务
    • Method_1 - Propagation.MANDATORY) Method_1 - 传播。强制性)
    • Method_2 - Transaction annotation only and throws exception Method_2 - 仅事务注释并抛出异常
    • Output: no record persist in database means rollback done.输出:数据库中没有持久记录意味着回滚完成。

    • OuterMethod - With transaction OuterMethod - 有事务
    • Method_1 - Propagation.REQUIRES_NEW) Method_1 - 传播.REQUIRES_NEW)
    • Method_2 - Propagation.REQUIRES_NEW) and throws 1/0 exception Method_2 - Propagation.REQUIRES_NEW) 并抛出 1/0 异常
    • Output: method_2 will throws exception so method_2 record not persisted.输出:method_2 将抛出异常,因此 method_2 记录不会持久化。
    • Output: method_1 will persist record in database.输出:method_1 将在数据库中持久化记录。
    • Output: There is no rollback for method_1输出:method_1 没有回滚

We can add for this:我们可以为此添加:

@Transactional(readOnly = true)
public class Banking_CustomerService implements CustomerService {

    public Customer getDetail(String customername) {
        // do something
    }

    // these settings have precedence for this method
    @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
    public void updateCustomer(Customer customer) {
        // do something
    }
}

You can use like this:你可以这样使用:

@Transactional(propagation = Propagation.REQUIRES_NEW)
public EventMessage<ModificaOperativitaRapporto> activate(EventMessage<ModificaOperativitaRapporto> eventMessage) {
//here some transaction related code
}

You can use this thing also:你也可以使用这个东西:

public interface TransactionStatus extends SavepointManager {
    boolean isNewTransaction();
    boolean hasSavepoint();
    void setRollbackOnly();
    boolean isRollbackOnly();
    void flush();
    boolean isCompleted();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM