spring (c) of the transaction, the transaction manager (TransactionManager) Introduction and four ways to achieve affairs

1, the transaction

        ACID a set of business operations, either all succeed or all unsuccessful.

       Transaction characteristics: ① Atomic for the whole (a transaction can not be resolved); ② consistency , for the purposes of data must be in a consistent state before and after (and perform a transaction execution, the transaction operation comprising either a all succeed or all fail, such as before the transfer, a and B have 250 yuan, switch 250 a to B, a has 0 yuan a result, there are 500 yuan B, a and B are added money, regardless of before or after transfer transfer are $ 500, which is consistency); ③ isolation for concurrent terms (any two concurrent transactions T1 and T2, T2 or T1 has ended before the start, or started after the end of T1, so each transaction not feel there are other transactions executed concurrently) ④ persistence , for the purposes of the results (means that once a transaction is committed, then changes to the data in the database is permanent)

(1) isolate the problem (transaction concurrency issues):

       ① dirty read : a transaction to read the contents of another uncommitted transactions (read uncommitted content); is a transaction to read the dirty data before another transaction rollback, such as modified during a transaction data B X, in before uncommitted (i.e., are not saved to the database before), transaction a reads X, and B has rolled back the transaction so that the transaction a dirty read is formed.

        ② non-repeatable read : refers to reading the same data multiple times in one transaction, read out the inconsistency of data. Such as inventory number 100, transaction number 100 Stock A read, transaction transaction B switch to turn on transaction B -> Save Stock Transaction B 50> submitted, which inventory database becomes 50, this time to switch back to Transaction A transaction a check once again found inventory is 50, so that the transaction a, in the same transaction twice read inconsistent account balance data, which is non-repeatable read .
       ③ phantom read : two transactions, the first transaction data for all rows modified, inserted into a second transaction data submission, submission of a transaction data is not found in a modification. For example, the system administrator A database of results from specific scores for all students instead ABCDE level, but the system administrator B would insert a specific record score at this time, when the end of the modified A system administrator found that there is a record do not change overnight, just like happened as hallucinations, this is called phantom reads.

(2) isolation level - decisive issues

Isolation Levels  Dirty read  Non-repeatable read Magic Reading Read lock
Uncommitted the Read (read uncommitted content) Yes Yes Yes  no
Committed the Read (read submission)  no  Yes  Yes  no
The Read Repeatable (repeatable read)  no  no  Yes  no
The Serializable (serializable)  no  no  no  Yes

    ① Read Uncommitted (read uncommitted content): there will be dirty reads, non-repeatable read, phantom read (the lowest level of isolation, high concurrency) [to ensure that the reading process is not illegal to read the data. Isolation level concurrency issues that handle multiple transactions]

  ②Read Committed (read submission): there will be non-repeatable read, phantom read problem (locked rows being read) [default transaction level most popular databases, to ensure that a transaction will not read another concurrent transaction modified but the data submitted, to avoid the "dirty read." This level is suitable for most systems. ]
  ③Repeatable the Read (Repeatable read): would a phantom read (read lock all rows) [guarantee a transaction will not be read by another transaction has been modified but not committed (rollback) data. Avoid the situation "dirty read" and "non-repeatable read" but brings more performance loss. ]

  ④Serializable (serialization): to ensure that all does not happen (the lock table) [most stringent level, transaction serial execution, resource consumption maximum. ]

  Non-repeatable read focus is modified: 
    the same conditions, you had to read the data, read out value is not the same again found 
  the magic of reading focuses on new or deleted 
    the same conditions, read out the 1st and 2nd the record number is not the same

       Solve the problem of non-repeatable read only lock to meet the conditions of the line, the need to solve the phantom read lock table.

2, PlatformTransactionManager transaction manager

      What (1) Transaction Manager is? Why Management?

         A transaction is a series of database operations (such as insert multiple data) unified commit or rollback , if you insert success, then together, if there is a middle of an exception, then all operations before the rollback, so that you can prevent appear dirty data, database data to prevent problems . This series of process we need to manage it.

         JDBC is through a Connection object transaction management, the default is automatically commit the transaction , you can manually shut down automatically submitted, submit by the method commit, rollback method to roll back, if you do not submit, then the data is not actually inserted into the database. Hibernate transaction management is carried out by the Transaction, the processing method is similar to the JDBC.

          Spring also has its own transaction management mechanism, generally use TransactionManager (Transaction Manager) to manage this function can be done by Spring injection.

     (2) first introduced two packages: spring-jdbc-3.2.0.RELEASE.jar and spring-tx-3.2.0.RELEASE.jar, even if the introduction Hibernate spring-orm-3.2.0.RELEASE. jar

3, transfer case (4 ways to realize the transaction)

(1) No transaction management

① create database tables account:

And inserting two data: id = 1, username = "jack", money = 1000 and id = 2, username = "rose", money = 1000.

②dao layer: Interface IAccountDao 

package com.gyf.dao;

public interface IAccountDao {
 
	//扣钱
	public void out(String outer,Integer money);
	//进账
	public void in(String inner,Integer money);
}

   Implementation class: AccountDaoImpl

package com.gyf.dao.impl;

import org.springframework.jdbc.core.support.JdbcDaoSupport;

import com.gyf.dao.IAccountDao;

public class AccountDaoImpl extends JdbcDaoSupport implements IAccountDao {

	@Override
	public void out(String outer, Integer money) {
		getJdbcTemplate().update("update account set money = money-? where username = ?", money,outer);
	}

	@Override
	public void in(String inner, Integer money) {
		getJdbcTemplate().update("update account set money = money+ ? where username =?", money,inner);
	} 

}

③service layer: Interface IAccountService

package com.gyf.service;

public interface IAccountService {

	/*转账
	 * @param outer 转出账号
	 * @param inner 转入账号
	 * @param money 转入金额
	 */
	public void transfer(String  outer,String inner,Integer money);
}

Implementation class: AccountServiceImpl

package com.gyf.service.impl;
import org.springframework.transaction.annotation.Transactional;

import com.gyf.dao.IAccountDao;
import com.gyf.service.IAccountService;
public class AccountServiceImpl2 implements IAccountService {
	private IAccountDao accountDao;//由spring注入
	public void setAccountDao(IAccountDao accountDao) {
		this.accountDao = accountDao;
	}

	@Override
	public void transfer(String outer, String inner, Integer money) {
		accountDao.out(outer, money);//扣钱
		
		accountDao.in(inner, money);//进账
	}

}

④web layer, beans09.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
                        https://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/context
                        https://www.springframework.org/schema/context/spring-context.xsd
                        http://www.springframework.org/schema/aop
                        https://www.springframework.org/schema/aop/spring-aop.xsd">
      
     <!-- 读取db.properties文件 -->
     <context:property-placeholder location="classpath:db.properties"/>
     <!-- 配置C3P0数据源 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
          <property name="driverClass" value="${driverClass}" />
           <property name="jdbcUrl" value="${jdbcUrl}" />
            <property name="user" value="${user}" />
             <property name="password" value="${password}" />
     </bean>
    <!-- 配置dao -->
    <bean id="accountDao" class="com.gyf.dao.impl.AccountDaoImpl">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    
    <!-- 配置service -->
    <bean id="accountService" class="com.gyf.service.impl.AccountServiceImpl">
       <property name="accountDao" ref="accountDao"></property>
    </bean>
    
    
</beans>

⑤test layer: lesson09

package com.gyf.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.gyf.service.IAccountService;
public class lesson09 {   
	@Test
	public void test1() {
		//转账测试
		//获取service		
		ApplicationContext context=new ClassPathXmlApplicationContext("beans09.xml");		
		IAccountService  accountService= (IAccountService) context.getBean("accountService");		
		accountService.transfer("jack", "rose", 100);
	}
}

Results of the:

(2) plus transaction (manual Management) (understand)

① modified service implementation class AccountServiceImpl layer

package com.gyf.service.impl;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import com.gyf.dao.IAccountDao;
import com.gyf.service.IAccountService;

public class AccountServiceImpl implements IAccountService {

	private IAccountDao accountDao;//由spring注入
	
	public void setAccountDao(IAccountDao accountDao) {
		this.accountDao = accountDao;
	}

	//spring配置事务模板【由spring注入】
	private TransactionTemplate transactionTemplate;
	
	public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
		this.transactionTemplate = transactionTemplate;
	}

	@Override
	public void transfer(String outer, String inner, Integer money) {
		
		this.transactionTemplate.execute(new TransactionCallbackWithoutResult() {
			
			@Override
			protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
				accountDao.out(outer, money);//扣钱
				int i=10/0;//此时执行的话,转账会失败,因为转账的过程出现了错误,事务会回滚
				accountDao.in(inner, money);//进账
				
			}
		});
		

	}

}

 ② modify the web layer, beans09.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
                        https://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/context
                        https://www.springframework.org/schema/context/spring-context.xsd
                        http://www.springframework.org/schema/aop
                        https://www.springframework.org/schema/aop/spring-aop.xsd">
      
     <!-- 读取db.properties文件 -->
     <context:property-placeholder location="classpath:db.properties"/>
     <!-- 配置C3P0数据源 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
          <property name="driverClass" value="${driverClass}" />
           <property name="jdbcUrl" value="${jdbcUrl}" />
            <property name="user" value="${user}" />
             <property name="password" value="${password}" />
     </bean>
    <!-- 配置dao -->
    <bean id="accountDao" class="com.gyf.dao.impl.AccountDaoImpl">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
   
    <!-- 配置事务管理器 -->
     <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
       <!-- 配置dataSource -->
       <property name="dataSource" ref="dataSource"></property>
     </bean>
     <!-- 配置事务模板 -->
    <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
      <!-- 事务管理器 -->
      <property name="transactionManager" ref="txManager"></property>
    </bean>
    
    <!-- 配置service -->
    <bean id="accountService" class="com.gyf.service.impl.AccountServiceImpl">
       <property name="accountDao" ref="accountDao"></property>
       <!-- 事务模板 -->
       <property name="transactionTemplate" ref="transactionTemplate"></property>
    </bean>
</beans>

Results of the:

Being given, in order to successfully transfer, put the service class AccountServiceImpl layer implementation of int i = 10/0; deleted or written off.

(3) generate a proxy bean plant, semi-automatic Management

①在service层,新建AccountServiceImpl2类

package com.gyf.service.impl;
import org.springframework.transaction.annotation.Transactional;
import com.gyf.dao.IAccountDao;
import com.gyf.service.IAccountService;
public class AccountServiceImpl2 implements IAccountService {
	private IAccountDao accountDao;//由spring注入
	public void setAccountDao(IAccountDao accountDao) {
		this.accountDao = accountDao;
	}
	@Override
	public void transfer(String outer, String inner, Integer money) {
		accountDao.out(outer, money);//扣钱
		//int i=10/0;
		accountDao.in(inner, money);//进账
	}

}

②在web层新建beans10.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
                        https://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/context
                        https://www.springframework.org/schema/context/spring-context.xsd
                        http://www.springframework.org/schema/aop
                        https://www.springframework.org/schema/aop/spring-aop.xsd">  
     <!-- 读取db.properties文件 -->
     <context:property-placeholder location="classpath:db.properties"/>
     <!-- 配置C3P0数据源 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
          <property name="driverClass" value="${driverClass}" />
           <property name="jdbcUrl" value="${jdbcUrl}" />
            <property name="user" value="${user}" />
             <property name="password" value="${password}" />
     </bean>
    <!-- 配置dao -->
    <bean id="accountDao" class="com.gyf.dao.impl.AccountDaoImpl">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!-- 配置事务管理器 -->
     <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
       <!-- 配置dataSource -->
       <property name="dataSource" ref="dataSource"></property>
     </bean> 
    <!-- 配置service -->
    <bean id="accountService" class="com.gyf.service.impl.AccountServiceImpl2">
       <property name="accountDao" ref="accountDao"></property>
    </bean>
      <!-- 配置工厂代理 -->
    <bean id="proxyService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
       <!-- 接口 -->
       <property name="proxyInterfaces" value="com.gyf.service.IAccountService"></property>
       <!-- 目标对象 -->
       <property name="target" ref="accountService"></property>
       <!-- 事务管理器 -->
       <property name="transactionManager" ref="txManager"></property>
       
       <!--transactionAttributes:事务属性/详情配置
            key:写方法名;value写事务配置;格式:PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly,-Exception,+Exception
                                                                                                                                  传播行为                                                隔离级别                             是否只读              异常回滚               异常提交
        -->
       <property name="transactionAttributes">
         <props>
            <prop key="transfer">PROPAGATION_REQUIRED,ISOLATION_DEFAULT</prop>
            <prop key="add">PROPAGATION_REQUIRED,ISOLATION_DEFAULT</prop>
            <prop key="delete">PROPAGATION_REQUIRED,ISOLATION_DEFAULT</prop>
            <prop key="update">PROPAGATION_REQUIRED,ISOLATION_DEFAULT</prop>
            <prop key="find">PROPAGATION_REQUIRED,ISOLATION_DEFAULT</prop>
         </props>
       </property>     
    </bean>
</beans>

③在test层新建lesson10类

package com.gyf.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.gyf.service.IAccountService;
public class lesson10 {  
	@Test
	public void test1() {
		//转账测试
		//获取service
		ApplicationContext context=new ClassPathXmlApplicationContext("beans10.xml");
		IAccountService  accountService= (IAccountService) context.getBean("proxyService");
		accountService.transfer("jack", "rose", 100);
	}
}

 

(4)基本aop的事务配置

新建web层beans11.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
     xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
                        https://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/context
                        https://www.springframework.org/schema/context/spring-context.xsd
                        http://www.springframework.org/schema/aop
                        https://www.springframework.org/schema/aop/spring-aop.xsd
                        http://www.springframework.org/schema/tx
                        https://www.springframework.org/schema/tx/spring-tx.xsd">
      
     <!-- 读取db.properties文件 -->
     <context:property-placeholder location="classpath:db.properties"/>
     <!-- 配置C3P0数据源 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
          <property name="driverClass" value="${driverClass}" />
           <property name="jdbcUrl" value="${jdbcUrl}" />
            <property name="user" value="${user}" />
             <property name="password" value="${password}" />
     </bean>
    <!-- 配置dao -->
    <bean id="accountDao" class="com.gyf.dao.impl.AccountDaoImpl">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
   
    <!-- 配置事务管理器 -->
     <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
       <!-- 配置dataSource -->
       <property name="dataSource" ref="dataSource"></property>
     </bean>
   
    <!-- 配置service -->
    <bean id="accountService" class="com.gyf.service.impl.AccountServiceImpl2">
       <property name="accountDao" ref="accountDao"></property>
    </bean>
     <!-- 使用aop标签来配置 -->
     
     <!--1、 配置事务通知管理器 -->
     <tx:advice id="txAdvice" transaction-manager="txManager">
       <!-- 事务详情 :传播行为,隔离级别-->
       <tx:attributes>
       <!-- 传播行为,隔离级别可以不用配置,但方法要配置-->
       <tx:method name="transfer" propagation="REQUIRED" isolation="DEFAULT"/>
       </tx:attributes>
     </tx:advice>
   
     <!-- 2、事务通知 与 切入点 关联 -->
      <aop:config>
      <!--   <aop:pointcut expression="execution(* com.gyf.service..*.*(..))" id="myPointcut"/>
         <aop:advisor advice-ref="" pointcut-ref="myPointcut"/> 等价于下面的代码 --> 
         <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.gyf.service..*.*(..))"/>
      </aop:config>    
</beans>

②新建test层lesson11

package com.gyf.test;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.gyf.service.IAccountService;

public class lesson11 {
     
	@Test
	public void test1() {
		//转账测试
		//获取service
		ApplicationContext context=new ClassPathXmlApplicationContext("beans11.xml");
		IAccountService  accountService= (IAccountService) context.getBean("accountService");
		accountService.transfer("jack", "rose", 100);
	}
}

(5)基本注解的事务配置

①修改service层的 AccountServiceImpl2

package com.gyf.service.impl;
import org.springframework.transaction.annotation.Transactional;
import com.gyf.dao.IAccountDao;
import com.gyf.service.IAccountService;
//@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT)功能和下面的一样
@Transactional
public class AccountServiceImpl2 implements IAccountService {
	private IAccountDao accountDao;//由spring注入
	public void setAccountDao(IAccountDao accountDao) {
		this.accountDao = accountDao;
	}
	@Override
	public void transfer(String outer, String inner, Integer money) {		
		accountDao.out(outer, money);//扣钱
		//int i=10/0;
		accountDao.in(inner, money);//进账
	}
}

②新建web层beans12.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
     xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
                        https://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/context
                        https://www.springframework.org/schema/context/spring-context.xsd
                        http://www.springframework.org/schema/aop
                        https://www.springframework.org/schema/aop/spring-aop.xsd
                        http://www.springframework.org/schema/tx
                        https://www.springframework.org/schema/tx/spring-tx.xsd">
      
     <!-- 读取db.properties文件 -->
     <context:property-placeholder location="classpath:db.properties"/>
     <!-- 配置C3P0数据源 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
          <property name="driverClass" value="${driverClass}" />
           <property name="jdbcUrl" value="${jdbcUrl}" />
            <property name="user" value="${user}" />
             <property name="password" value="${password}" />
     </bean>
    <!-- 配置dao -->
    <bean id="accountDao" class="com.gyf.dao.impl.AccountDaoImpl">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!-- 配置service -->
    <bean id="accountService" class="com.gyf.service.impl.AccountServiceImpl2">
       <property name="accountDao" ref="accountDao"></property>
    </bean>
     <!-- 注解的事务配置 -->
     <!--1、 配置事务管理器 -->
     <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
       <!-- 配置dataSource -->
       <property name="dataSource" ref="dataSource"></property>
     </bean>   
     <!-- 2、开启事务注解驱动 -->
      <tx:annotation-driven transaction-manager="txManager"/>
</beans>

③新建test层的lesson12

package com.gyf.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.gyf.service.IAccountService;
public class lesson12 { 
	@Test
	public void test1() {
		//转账测试
		//获取service
		ApplicationContext context=new ClassPathXmlApplicationContext("beans12.xml");
		IAccountService  accountService= (IAccountService) context.getBean("accountService");
		accountService.transfer("jack", "rose", 100);
	}
}

 

发布了57 篇原创文章 · 获赞 36 · 访问量 6万+

Guess you like

Origin blog.csdn.net/hqy1719239337/article/details/97944775