[Turn] in-depth analysis of usage @Transactional

Keywords: affairs, programmatic transaction, declarative transaction, spring transaction management, AOP enhancements affairs, @ Transactional

 

Before analyzing in-depth analysis of the @Transactional, let's review some of the basic elements of the transaction.

The basic concept of the transaction

First look at the basic concepts and features of the transaction. Database transaction (Database Transaction), refers to a series of operations performed by a single logical unit of work, or fully executed or not executed completely. Transaction, it must have ACID properties, i.e. atomicity (Atomicity), consistency (Consistency), isolation (Isolation) and persistent (Durability).

Programmatic and declarative transaction Affairs

Spring and Hibernate transaction management to achieve integration is commonly used as a function. Hibernate is recommended that all database access should be placed within a transaction carried out, even if only read-only operations. Transaction and should be as short as possible, as long transaction would not lead to the release of a long table expert-level lock, thereby reducing system concurrent performance. Spring supports both programmatic and declarative transaction transaction.

 

Programmatic transaction management needs related to the transaction explicitly call beginTransaction code (), commit (), rollback () and so on. Spring's declarative transaction management on the ground floor is based on the AOP, which is essentially a method to intercept before and after, and then create or join a transaction before the target method begins, submitted in accordance with the implementation after executing the target method or roll back the transaction. AOP transaction also enhances the use of force is a big place.

 

Declarative transaction

The biggest advantage is declarative transaction does not need to programmatically manage transactions, transaction management so you do not need doping code in the business logic code, just do the relevant business rules declared in the configuration file, well separated business logic and transaction management logic. To increase spring + jpa integrated declarative transaction, for example, the following is the use configuration and the use of declarative transactions.

applicationContext.xml Configuration

<! - Configure entityManagerFactory Configuration ->

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">

     <property name="dataSource" ref="dataSource" />

     <property name="persistenceXmlLocation" value="/WEB-INF/classes/persistence.xml" />

     <property name="loadTimeWeaver">

             <bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />

     </property>

</bean>

 

<! - Configure declarative transaction management, use JpaTransactionManager as a transaction manager implementation class ->

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">

          <property name="entityManagerFactory" ref="entityManagerFactory" />

</bean>

 

<! - statement generated business components using annotations Service agent ->

<tx:annotation-driven transaction-manager="transactionManager" />

@Transactional configured using declarative transaction management

After configuring and annotation-driven transaction management in spirng configuration file, we can configure the declarative transaction management in the business layer using @Transactional. as follows

 

@Service

@Transactional

public class BaseService<T> implements IBaseService<T> {

 

@Autowired

private IBaseDao<T> baseDao;

......

}

 

@Transactional further use

Above we already know the usage declarative transaction management, here we will further analyze @Transactional usage in a variety of scenarios.

Propagation behavior Affairs

@Transactional annotation support 9 setting properties, which the Propagation property is used to enumerate the transaction propagation behavior. The so-called transaction propagation behavior is when multiple transactions method call each other, how transactions propagate between these methods. Spring supports seven transaction propagation behavior:

 

 

 

REQUIRED transaction propagation behavior is common, if no transaction creates a new transaction, if there is already a transaction, added to this transaction. Other propagation behavior it can separate inspection.

When nested transaction propagation method is called multiple transactions

There are three methods to call the transaction nesting relationship as follows:

 

PayHisInfoService.update()->PayHisInfoService.save()->PayInfoService.update()

 

@Transactional(propagation=Propagation.REQUIRED)

public abstract class BaseService<E>{

          public abstract List<E> findAll();

}

 

@Component

public class PayHisInfoService extends BaseService<PayHisInfo>{

       @Resource

       private PayHisInfoDao payHisInfoDao;

@Resource

private PayInfoService payInfoService;

 

       public  void update(PayHisInfo payHisInfo,PayInfo payInfo){

     save(payHisInfo);

            payInfoService.update(payInfo);

      }

      public int save(PayHisInfo payHisInfo){

         return payHisInfoDao.insert(payHisInfo);

      }

}

 

@Component

public class PayInfoService extends BaseService<PayInfo>{

     @Resource

     private transient PayInfoDao payInfoDao;

 

     @Override

     @Transactional(propagation=Propagation.SUPPORTS, readOnly=true)

     public List<PayInfo> findAll() {

            return payInfoDao.findAll();

     }

 

     public int update(PayInfo payInfo){

            return payInfoDao.update(payInfo);

     }

}

 

 

When we call nesting relationship accordance with the above, the following results

 

 

 

 

 

We can see from the log, open a transaction when PayHisInfoService.update () execution, and PayHisInfoService.save () method and PayHisInfoService.update () method in the same class, the transaction propagation does not occur when you call, as has been in PayHisInfoService.update () method of affairs among the same. When executed PayInfoService.update (), suggesting "Participating in existing transaction", which shows that there is transaction propagation, namely PayInfoService.update () does not create a new transaction, but added to the existing PayHisInfoService.update () Transaction in.

Transaction propagation in a multithreaded environment

Now we will in the example above PayHisInfoService.update () is executed by another thread, as follows

 

@Component

public class PayHisInfoService extends BaseService<PayHisInfo>{

    @Resource

    private PayHisInfoDao payHisInfoDao;

    @Resource

    private PayInfoService payInfoService;

 

    public  void update(PayHisInfo payHisInfo,PayInfo payInfo){

          save(payHisInfo);

           //payInfoService.update(payInfo);

         PayInfoThread pifth = new PayInfoThread(payInfoService,payInfo);

         pifth.start();

     }

 

     public int save(PayHisInfo payHisInfo){

          return payHisInfoDao.insert(payHisInfo);

     }

 

     private class PayInfoThread extends Thread{

        private PayInfoService payInfoService;

        private PayInfo payInfo;

       

        private PayInfoThread(PayInfoService payInfoService,PayInfo payInfo) {

            this.payInfoService = payInfoService;

            this.payInfo = payInfo;

        }

        public void run() {

               System.out.println("PayInfoThread updating payInfo...");

               payInfoService.update(payInfo);

        }

  }

}

 

When we call nesting relationship accordance with the above, the following results

 

 

 

 

As can be seen from the log results in the implementation of PayHisInfoService.update () and PayInfoService.update (), respectively, to create their own affairs. The PayHisInfoService.save () and PayHisInfoService.update () is executed in the same thread. So spring transaction management is thread-safe.

Nested transaction method calls in the same thread work in the same transaction. If these nested method calls work in a different thread, the transaction method in different threads work in a separate transaction.

Inheritance of @Transactional

Perhaps you've seen in the above example, we only @Transactional declared in the parent class BaseService, the subclass naturally been enhanced affairs. Notes did not inherit this argument, but here used to describe the "inheritance" relationship between the parent and child class method @Transactional most fitting: the parent class Service declares @Transactional, subclass inherits the parent class, parent All methods will @Transactional subclass of the class declaration transaction enhancements. That there is a very practical uses, such as testing the base class inheritance

AbstractTransactionalJUnit4SpringContextTests

Statement @Transactional easy transaction testing

 

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration("/applicationContext.xml")

@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)

@Transactional

public class BaseTest extends AbstractTransactionalJUnit4SpringContextTests {

        public Object getBean(String beanName){

                return applicationContext.getBean(beanName);

         }

}

 

@Transactional to BaseTest declared after, it will automatically give all our own testing methods written test class transactional enhancements.

@Transactional priority

If the method subclass overrides the parent class and declares @Transactional, then the transaction statement subclass takes precedence over affairs statement of the parent class.

Use AOP spring of transaction enhancement section

Liezi or above, the parent class declaration @Transactional removed. In applicationContext.xml configure affairs enhancement section, configured as follows:

 

<-! ② use aop and tx namespace syntax to add enhancements to the transaction PayHisInfoService all public methods ->

    <aop:config proxy-target-class="true">

        <aop:pointcut id="serviceJdbcMethod"

        expression="execution(public * com.xxx.service.PayHisInfoService.*(..))"/>

        <aop:advisor pointcut-ref="serviceJdbcMethod" advice-ref="jdbcAdvice" order="0"/>

    </aop:config>

    <tx:advice id="jdbcAdvice" transaction-manager="transactionManager">

        <tx:attributes>

            <tx:method name="*"/>

        </tx:attributes>

    </tx:advice>

 

Run the test case results are as follows:

 

 

 

 

When there is a data update fails, the transaction will automatically rollback, as follows:

 

 

Method visibility @Transactional

In order to facilitate the above tests demonstrate, we are @Transactional statement on the class. @Transactional may actually act on the interface, the interface methods, classes, and class method. But the group does not recommend using the Spring annotation on an interface or an interface method, because it is only used when the agent interface based on it to take effect. In addition, @Transactional annotation should only be applied to public method, which is determined by the nature of Spring AOP (enhancement can be seen from the above Spring AOP affairs, is directed to a method of). If you're protected, private or default on the method of use @Transactional annotation visibility, it will be ignored, and no exception is thrown.

 

to sum up

(1) declarative transactions than programmatic transaction

(2) nested calls the transaction method results in a transaction propagation

(3) spring transaction management is thread-safe

All methods will @Transactional subclass (4) a statement of the parent class transactional enhancements

(5) from Spring AOP nature watching, @ Transactional annotation should only be applied to public method

 

 

Reference Documents

http://www.ibm.com/developerworks/cn/java/j-lo-spring-ts3/

http://www.ibm.com/developerworks/cn/education/opensource/os-cn-spring-trans/

Author: ITPSC
Source: http://www.cnblogs.com/hjwublog/

Guess you like

Origin www.cnblogs.com/gaobing1252/p/11110662.html