zoukankan      html  css  js  c++  java
  • Spring框架:第八章:声明式事务

    10、声明式事务
    事务分为声明式和编程式两种:
    声明式事务:声明式事务是指通过注解的形式对事务的各种特性进行控制和管理。
    编码式(编程式)事务:指的是通过编码的方式实现事务的声明。

    11.1、编码方式实现事务:
    在这里插入图片描述
    11.2、声明式事务环境搭建
    11.2.1、准备测试数据库

    ##创建tx数据库
    drop database if exists `tx`;
    CREATE database `tx`;
    ##切换tx数据库
    USE `tx`;
    
    ##删除用户表
    DROP TABLE IF EXISTS `user`;
    ##创建用户表
    CREATE TABLE `user` (
      `id` int primary key auto_increment,	
      `username` varchar(50) NOT NULL,
      `money` int(11) DEFAULT NULL
    );
    ##插入数据
    insert  into `user`(`username`,`money`) values ('张三',1000),('李四',1000);
    
    ##删除图书表
    drop table if exists `book`;
    ##创建图书表
    create table `book`(
        `id` int primary key auto_increment,
        `name` varchar(500) not null,
        `stock` int
    );
    ##插入数据
    insert into book(`name`,`stock`) values('java编程思想',100),('C++编程思想',100);
    
    ##查看数据
    select * from book;
    select * from user;
    

    11.2.2、创建一个Java工程,导入Jar包
    在这里插入图片描述
    导入jar包:

    com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
    commons-logging-1.1.3.jar
    druid-1.1.9.jar
    mysql-connector-java-5.1.37-bin.jar
    spring-aop-4.3.18.RELEASE.jar
    spring-beans-4.3.18.RELEASE.jar
    spring-context-4.3.18.RELEASE.jar
    spring-core-4.3.18.RELEASE.jar
    spring-expression-4.3.18.RELEASE.jar
    spring-jdbc-4.3.18.RELEASE.jar
    spring-orm-4.3.18.RELEASE.jar
    spring-test-4.3.18.RELEASE.jar
    spring-tx-4.3.18.RELEASE.jar
    

    配置jdbc.properties属性配置文件:

    url=jdbc:mysql://localhost:3306/tx
    user=root
    password=root
    driverClassName=com.mysql.jdbc.Driver
    initialSize=5
    maxActive=10
    

    配置Spring的配置文件:

    <?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"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
    
    	<!-- 配置包扫描 -->
    	<context:component-scan base-package="com"></context:component-scan>
    
    	<!-- 加载jdbc.properties属性配置文件 -->
    	<context:property-placeholder location="classpath:jdbc.properties"/>
    	
    	<!-- 配置数据库连接池 -->
    	<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    		<property name="username" value="${user}"/>
    		<property name="password" value="${password}"/>
    		<property name="url" value="${url}"/>
    		<property name="driverClassName" value="${driverClassName}"/>
    		<property name="initialSize" value="${initialSize}" />
    		<property name="maxActive" value="${maxActive}"/>
    	</bean>
    	
    	<!-- 配置jdbcTemplate工具类 -->
    	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    		<property name="dataSource" ref="dataSource" />
    	</bean>	
    </beans>
    

    11.3、测试Service的默认事务
    实验1:测试service服务层的默认事务

    @Repository
    public class BookDao {
    
    	@Autowired
    	JdbcTemplate jdbcTemplate;    	
    	public void updateBook() {
    		jdbcTemplate.update("update book set name = '图书表被修改了'");
    	}    	
    }
    
    
    @Repository
    public class UserDao {
    
    	@Autowired
    	JdbcTemplate jdbcTemplate;    	
    	public void updateUser() {
    		jdbcTemplate.update("update user set username = '用户表被修改了'");
    	}    	
    }
    
    @Service
    public class TransactionService {
    
    	@Autowired
    	private UserDao userDao;  	
    	@Autowired
    	private BookDao bookDao;    	
    	public void multiUpdate() {
    		userDao.updateUser();
    		bookDao.updateBook();
    	}	
    }
    

    异常的演示

    @Service
    public class TransactionService {
    
    	@Autowired
    	private UserDao userDao;
    	
    	@Autowired
    	private BookDao bookDao;
    	
    	public void multiUpdate() {
    		userDao.updateUser();
    		int i = 12 / 0 ;
    		bookDao.updateBook();
    	}
    }
    

    Spring事务引入的分析------PlatformTransactionManager类简单介绍

    事务管理器实现类
    在这里插入图片描述

    由于我们使用的是数据库连接池访问数据库,所以事务管理器使用的是DataSourceTransactionManager。
    在这里插入图片描述

    11.4、使用Spring的注解声明事务管制
    实验2:测试Spring的声明式事务

    1、在需要事务的方法上加入注解。

    /**
     * @Transactional 表示当前方法有事务
     */
    @Transactional
    public void multiUpdate() {
    	userDao.updateUser();
    	int i = 12 / 0 ;
    	bookDao.updateBook();
    }
    

    2、配置事务管理器驱动

    <!-- 事务管理器 -->
    <bean id="transactionManager" 
    	class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    	<property name="dataSource" ref="dataSource"/>	
    </bean>
    

    3、配置事务注解驱动

    <!-- 
    	<tx:annotation-driven/> 开启注解的事务驱动 启用代理
    		transaction-manager="transactionManager" 配置事务管理器
    		如果事务管理器的id值是transactionManager,则事务管理器属性可以省略
     -->
    <tx:annotation-driven />
    

    11.5、noRollbackFor和noRollbackForClassName测试不回滚的异常
    实验3:noRollbackFor和noRollbackForClassName测试不回滚的异常

    	/**
    	 * @Transactional 表示当前方法有事务<br/>
    	 * 	默认情况下。RuntimeException运行时异常和运行时子异常。都会回滚事务<br/>
    	 * noRollbackFor=java.lang.ArithmeticException.class 表示算术异常不回滚事务<br/>
    	 * noRollbackFor= {java.lang.ArithmeticException.class,java.lang.NullPointerException.class}<br/>
    	 * noRollbackForClassName="java.lang.NullPointerException" 设置哪些类名的异常不回滚事务<br/>
    	 */
    	@Transactional(noRollbackForClassName="java.lang.NullPointerException")
    	public void multiUpdate() {
    		userDao.updateUser();
    //		int i = 12 / 0 ;
    		Object object = null;
    		System.out.println( object.toString() );
    		bookDao.updateBook();
    	}
    

    11.6、自定义设置回滚异常
    实验5:rollbackFor和rollbackForClassName回滚的异常

    /**
     * @throws FileNotFoundException 
     * @Transactional 表示当前方法有事务<br/>
     * 	默认情况下。RuntimeException运行时异常和运行时子异常。都会回滚事务<br/>
     * rollbackFor=FileNotFoundException.class 设置当抛出FileNotFoundException异常时,回滚事务<br/>
     * rollbackForClassName="java.io.FileNotFoundException" 设置当抛出FileNotFoundException异常时就会回滚事务<br/>
     */
    @Transactional(rollbackForClassName="java.io.FileNotFoundException")
    public void multiUpdate() throws FileNotFoundException {
    	userDao.updateUser();
    	int i = 12 ;
    	if (i == 12) {
    		throw new FileNotFoundException();
    	}
    	bookDao.updateBook();
    }
    

    11.7、事务的只读属性
    实验4:测试readOnly只读属性

    /**
     * @throws FileNotFoundException 
     * @Transactional 表示当前方法有事务<br/>
     * 	默认情况下。RuntimeException运行时异常和运行时子异常。都会回滚事务<br/>
     * readOnly=false 表示当前方法可以执行读操作。也可以执行写操作(指的是sql语句)。<br/>
     * 修改、添加、删除、是写操作、select查询语句是读操作。<br/>
     * readOnly=true 表示当前方法只能执行查询操作<br/>
     */
    @Transactional(readOnly=true)
    public void multiUpdate() throws FileNotFoundException {
    	userDao.updateUser();
    	bookDao.updateBook();
    }
    

    只读的方法执行修改语句报错。
    在这里插入图片描述
    11.8、事务超时属性timeout(秒为单位)

    /**
     * @throws FileNotFoundException 
     * @Transactional 表示当前方法有事务<br/>
     * 	默认情况下。RuntimeException运行时异常和运行时子异常。都会回滚事务<br/>
     * timeout=3 表示3秒之后就超时,不允许再执行sql语句
     */
    @Transactional(timeout=3)
    public void multiUpdate() throws FileNotFoundException {
    	userDao.updateUser();
    	try {
    		Thread.sleep(5000);
    	} catch (InterruptedException e) {
    		e.printStackTrace();
    	}
    	bookDao.updateBook();
    }
    

    当执行时间超过指定的秒钟后就会超时:
    在这里插入图片描述
    11.10、事务的传播特性propagation
    什么是事务的传播行为:
    当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行。
    事务的传播行为可以由传播属性指定。Spring定义了7种类传播行为。

    事务的传播特性,有以下几种类型:
    在这里插入图片描述

    11.11、注解演示事物传播特性
    UserService
    BookService
    TransactionService

    实验1:大小事务传播特性都是REQUIRED

    	@Transactional(propagation = Propagation.REQUIRED)
    	public void multlTransaction() {
    	@Transactional(propagation = Propagation.REQUIRED)
    	public void updateBook() {
    @Transactional(propagation=Propagation.REQUIRED)
    public void updateUser() {
    

    在这里插入图片描述
    实验2:大小事务传播特性都是REQUIRES_NEW

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void multiUpdate()
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void updateBook()
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void updateUser()
    

    在这里插入图片描述

    实验3:大事务是REQUIRED,小事务都是REQUIRES_NEW

    @Transactional(propagation = Propagation.REQUIRED)
    public void multiUpdate()
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void updateBook()
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void updateUser()
    

    在这里插入图片描述

    实验4:大事务是REQUIRED,小1REQUIRED,小2REQUIRES_NEW

    @Transactional(propagation = Propagation.REQUIRED)
    public void multiUpdate()
    @Transactional(propagation = Propagation.REQUIRED)
    public void updateBook()
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void updateUser()
    

    在这里插入图片描述

    实验5:大事务是REQUIRED,小1REQUIRES_NEW,小2REQUIRED

    @Transactional(propagation = Propagation.REQUIRED)
    public void multiUpdate()
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void updateBook()
    @Transactional(propagation = Propagation.REQUIRED)
    public void updateUser()
    

    在这里插入图片描述
    12、xml配置式事务声明
    复制原来注解事务管理的工程。去掉里面所有@Transactional的注解。

    <?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:tx="http://www.springframework.org/schema/tx"
    	xmlns:aop="http://www.springframework.org/schema/aop"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
    		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
    		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
    
    	<!-- 配置包扫描 -->
    	<context:component-scan base-package="com"></context:component-scan>
    
    	<!-- 加载jdbc.properties属性配置文件 -->
    	<context:property-placeholder location="classpath:jdbc.properties"/>
    	
    	<!-- 配置数据库连接池 -->
    	<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    		<property name="username" value="${user}"/>
    		<property name="password" value="${password}"/>
    		<property name="url" value="${url}"/>
    		<property name="driverClassName" value="${driverClassName}"/>
    		<property name="initialSize" value="${initialSize}" />
    		<property name="maxActive" value="${maxActive}"/>
    	</bean>
    	
    	<!-- 配置jdbcTemplate工具类 -->
    	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    		<property name="dataSource" ref="dataSource" />
    	</bean>
    	
    	<!-- 
    		配置事务管理器
    	 -->
    	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    		<property name="dataSource" ref="dataSource" />
    	</bean>
    	
    	<!-- 
    		配置事务属性
    	 -->
    	<tx:advice id="tx_advice" transaction-manager="transactionManager">
    		<tx:attributes>
    			<!-- 
    				tx:method 给某个方法配置事务属性
    					name就是方法的匹配规则(方法名)
    					
    					精确匹配
    			 -->
    			<tx:method name="updateUser" propagation="REQUIRED"/>
    			<!-- 
    				给save*方法配置事务属性
    					name="save*"	表示给save字符串打头的方法配置事务属性
    			 -->
    			<tx:method name="save*" propagation="REQUIRED"/>
    			<tx:method name="update*" propagation="REQUIRES_NEW"/>
    			<tx:method name="delete*" propagation="REQUIRED"/>
    			<tx:method name="multlTransaction" propagation="REQUIRES_NEW"/>
    			<!-- 
    				<tx:method name="*"/> 所有的方法
    					read-only="true" 剩下的方法都是查询操作。
    			 -->
    			<tx:method name="*" read-only="true"/>
    		</tx:attributes>
    	</tx:advice>
    
    	<aop:config>
    		<!-- 
    			aop:advisor 配置通知
    		 -->
    		<aop:advisor advice-ref="tx_advice" 
    			pointcut="execution(public * com.service..*Service*.*(..))"/>
    	</aop:config>
    	
    </beans>
    
  • 相关阅读:
    C# 依据鼠标坐标取网页内成员坐标.ie
    C# WebBrowser获取指定字符串的坐标
    C#获取网页中某个元素的位置,并模拟点击
    qq空间认证教程:借助企鹅媒体平台认证QQ公众空间
    QQ空间认证之数据篇
    QQ空间运营 怎么做一个QQ人气号?
    QQ空间|qq人气号怎么赚钱?
    QQ好友的价值玩法 及如何搞到几万好友?
    新媒体运营之如何月涨十万粉
    社群经济:如何利用社群做营销?
  • 原文地址:https://www.cnblogs.com/javawxid/p/12812078.html
Copyright © 2011-2022 走看看