Spring详解四之声明式事务

1、声明式事务

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

3、注解式事务声明

4xml配置式事务声明

5Spring整合Web

1、声明式事务

事务分为声明式和编程式两种:

声明式事务:声明式事务是指通过注解的形式对事务的各种特性进行控制和管理。

编码式(编程式)事务:指的是通过编码的方式实现事务的声明。

 

1.1、编码方式实现事务:

Spring详解四之声明式事务_第1张图片

1.2、声明式事务环境搭建

1.2.2、准备测试数据库


##创建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;

1.2.2、创建一个Java工程,导入Jar

Spring详解四之声明式事务_第2张图片

JavaBean对象


public class Book {

	private Integer id;
	private String name;
private int stock;

public class User {

	private Integer id;
	private String username;
	private int money;

Dao

@Repository
public class BookDao {

	@Autowired
	private JdbcTemplate jdbcTemplate;

	public int updateBook() {
		String sql = "update book set name = '**我被修改了!**' where id = 1";
		return jdbcTemplate.update(sql);
	}

}

@Repository
public class UserDao {

	@Autowired
	private JdbcTemplate jdbcTemplate;

	public int updateUser() {
		String sql = "update user set username = '**我被修改了**' where id = 1";
		return jdbcTemplate.update(sql);
	}

}

Service代码

@Service
public class TransactionService {

	@Autowired
	private UserDao userDao;

	@Autowired
	private BookDao bookDao;

	public void updateTwoTable() {
		userDao.updateUser();
		bookDao.updateBook();
	}

}

1.3测试Service的默认事务

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

@ContextConfiguration(locations = "classpath:application.xml")
@RunWith(SpringJUnit4ClassRunner.class)
public class SpringTest {

	@Autowired
	private DataSource dataSource;

	@Autowired
	private JdbcTemplate jdbcTemplate;
	
	@Autowired
	private TransactionService transactionService;

	@Test
	public void testDataSource() throws Exception {
		System.out.println(dataSource.getConnection());
	}
	
	@Test
	public void testJdbcTempalte() throws Exception {
		System.out.println( jdbcTemplate );
	}
	
	@Test
	public void testTransaction() throws Exception {
		transactionService.updateTwoTable();
	}

}

异常的演示

public void updateTwoTable() {
		userDao.updateUser();
		int i = 12 / 0;
		bookDao.updateBook();
	}

结果:

Spring详解四之声明式事务_第3张图片Spring详解四之声明式事务_第4张图片

但结果却是一张表更新了,另一种表未更新就发生异常,导致两张表不能同步,经典案例就是银行的转账,这边转过去了,对方没有收到。这里就要用到事务来处理了,要是在同一个事务中有一处出错,整个事务都回滚,从而阻止这种非一致性的更新操作。

Spring详解四之声明式事务_第5张图片

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

 

PlatformTransactionManager接口,提供所有事务操作规范。我们使用DataSource数据库连接池,使用的事务管理器是DataSourceTransactionManager

Spring详解四之声明式事务_第6张图片

Spring详解四之声明式事务_第7张图片

注:和JavawebFilterjdk动态代理、aopUtilsjdbc的原理一样分三层结构处理业务

3、注解式事务声明

3.1使用Spring的注解式声明事务管制

实验2:测试Spring的声明式事务

 

先导入AOP包,因为Spring的底层事务使用到了aop功能

com.springsource.org.aopalliance-1.0.0.jar

com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar

spring-aop-4.0.0.RELEASE.jar

spring-aspects-4.0.0.RELEASE.jar

配置Spring的事务需要的切面类DataSourceTransactionManager


	
	
			
	

Spring的配置文件中加入tx名称空间

Spring详解四之声明式事务_第8张图片

在Spring的配置文件中



	

还需要在Service的事务方法中添加@Transactioaln注解

@Transactional
	public void updateTwoTable() {
		userDao.updateUser();
		int i = 12 / 0;
		bookDao.updateBook();
	}

3.2noRollbackFornoRollbackForClassName测试不回滚的异常

实验3noRollbackFornoRollbackForClassName测试不回滚的异常

/**
	 * noRollbackFor=ArithmeticException.class 表示当接收到数学异常之后。不回滚
* noRollbackForClassName="java.lang.ArithmeticException" 表示当接收到指定字符串表示的全类名的异常的时候,不回滚事务 */ @Transactional(noRollbackFor=ArithmeticException.class) public void updateTwoTable() { userDao.updateUser(); int i = 12 / 0; bookDao.updateBook(); }

Book:

Spring详解四之声明式事务_第9张图片

User表:

Spring详解四之声明式事务_第10张图片

注:spring默认回滚的是运行时异常RuntimeExceptionRuntimeException的子异常

Spring详解四之声明式事务_第11张图片

3.3、自定义设置回滚异常

实验5rollbackForrollbackForClassName回滚的异常

Spring默认回滚的是RuntimeException,运行时异常或运行时异常的子异常


/**
	 * spring默认回滚的是运行时异常RuntimeException和RuntimeException的子异常
* rollbackFor=FileNotFoundException.class 表示FileNotFoundException也会回滚 * rollbackForClassName="java.io.FileNotFoundException" 表示当出现配置字符串所表示的全类名的异常的时候。也会回滚事务 * @throws FileNotFoundException * */ @Transactional(rollbackFor=FileNotFoundException.class) public void updateTwoTable() throws FileNotFoundException { userDao.updateUser(); int i = 0; if (i == 0) {//java.io.FileNotFoundException throw new FileNotFoundException("sadf"); } bookDao.updateBook(); }

3.3、事务的只读属性

实验4:测试readOnly只读属性

/**
	 * readOnly 如果值为true。表示只支持查询操作。不支持写操作
* 
如果设置为false,支持全部 */ @Transactional(readOnly=true) public void updateTwoTable() throws FileNotFoundException { userDao.updateUser(); bookDao.updateBook(); }


3.4、事务超时属性timeout(秒为单位)

timeout=3表示操作不能超过3秒,否在就包错


@Transactional(timeout=3)
	public void updateTwoTable() throws FileNotFoundException {
		userDao.updateUser();
		try {
			Thread.sleep(4000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		bookDao.updateBook();
	}

3.5、事务的传播特性propagation

什么是事务的传播行为:

当事务方法(XxxService())被另一个事务方法调用时,必须指定事务应该如何传播。例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行。

事务的传播行为可以由传播属性指定。Spring定义了7种类传播行为。

 

事务的传播特性,有以下几种类型:(常用的就前两种,所以下面进行这两种的测试)required默认的

Spring详解四之声明式事务_第12张图片

3.6、注解演示事物传播特性

因为事务方法是被其他事务方法调用所以,添加几个事务方法进行测试

UserService

BookService

TransactionService

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

实验2:大小事务传播特性都是REQUIRES_NEW

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

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

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

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

	@Transactional(propagation = Propagation.REQUIRED)
	public void multiUpdate() {
	@Transactional(propagation = Propagation.REQUIRED)
	public void updateBook() {
        @Transactional(propagation=Propagation.REQUIRED)
        public void updateUser() {
Spring详解四之声明式事务_第13张图片

实验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()
Spring详解四之声明式事务_第14张图片

实验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()
Spring详解四之声明式事务_第15张图片

实验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()
Spring详解四之声明式事务_第16张图片

实验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()
Spring详解四之声明式事务_第17张图片

4xml配置式事务声明

去掉。所有@Transactional的注解。

当然注解有的功能,xml也可以实现



	
			
	

	
	
		
		
			
			
			
			
		
	

	
	
		
	

总结:使用jdbcTemplate或者是事务管理器 属性都要引用数据源,因为都是在数据库连接的基础上操作的。

总结:注解方式和配置文件方式的事务

(1)、无论哪种方式,默认都是propagation="REQUIRED"方式

(2)、无论哪种方式,默认值都是:transaction-manager="transactionManager"

3)、无论哪种方式,都要有事务管理器---管理事务的切面类-DataSourceTransactionManager

advice - advisor :建议 ,顾问

配置文件情况下:一、(为什么用aop.jar包?因为事务的底层是用aop的三层结构实现的,学习aop的主要作用就是处理事务)


	
		
	

二、还有事务的特性配置

注解方法情况下:在Spring的配置文件中


	

这里的transaction-manager="transactionManager"一般如果切面类的id值是transactionManager,这里就可以省略了,阴谋在事务的注解驱动里,默认是这个值的。但如果切面类的管理器的id不是这个值,这里就一定要加上对应的值了。

5Spring整合Web

5.1在web工程中添加Springjar包。

Spring的核心包

spring-beans-4.0.0.RELEASE.jar

spring-context-4.0.0.RELEASE.jar

spring-core-4.0.0.RELEASE.jar

spring-expression-4.0.0.RELEASE.jar

aop

spring-aop-4.0.0.RELEASE.jar(注解,包扫描)

spring-aspects-4.0.0.RELEASE.jar

com.springsource.org.aopalliance-1.0.0.jar

com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar

JDBC-ORM

spring-jdbc-4.0.0.RELEASE.jar

spring-orm-4.0.0.RELEASE.jar

spring-tx-4.0.0.RELEASE.jar(事务管理)

Springweb整合包

spring-web-4.0.0.RELEASE.jar

测试包

spring-test-4.0.0.RELEASE.jar

 

 

整合SpringWeb容器分两个步骤:

1、导入spring-web-4.0.0.RELEASE.jar

2、在web.xml配置文件中配置org.springframework.web.context.ContextLoaderListener(直接提示导入,无需记忆)监听器监听ServletContext的初始化

3、在web.xml配置文件中配置contextConfigLocation上下文参数。配置Spring配置文件的位置,以用于初始化Spring容器

5.2在web.xml中配置

  
  	contextConfigLocation
  	classpath:applicationContext.xml
  
  
  	org.springframework.web.context.ContextLoaderListener
  

5.3获取WebApplicationContext上下文对象的方法如下:

方法一(官方推荐):

WebApplicationContextUtils.getWebApplicationContext(getServletContext())

 

 

方法二(不推荐):

getServletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);


Spring详解三之AOP与数据访问

常用spring开发jar包即额外包下载


你可能感兴趣的:(Spring)