目录
1:spring的7中事务传播行为
2:Spring对应数据库中的事务隔离级别
3:Spring事务接口简介
3.1:PlatformTransactionManager (平台事务管理器)
3.2:TransactionStatus 事务状态
3.3:TransactionDefinition 事务定义
4:Spring实现事务主要有两种方式
5:公共代码
6:编程式事务实现
6.1:PlatformTransactionManager实现
6.2:TransactionTemplate实现
6.3:基于TransactionProxyFactoryBean (bean工厂代理)--需要显示的为每一个业务类配置,每多一个业务类就要进行添加
7:声明式事务实现
7.1:基于配置文件
7.2:基于注解实现声明式事务
传播行为 |
含义 |
propagation_required(xml文件中为required) |
表示当前方法必须在一个具有事务的上下文中运行,如有客户端有事务在进行,那么被调用端将在该事务中运行,否则的话重新开启一个事务。(如果被调用端发生异常,那么调用端和被调用端事务都将回滚) |
propagation_supports(xml文件中为supports) |
表示当前方法不必需要具有一个事务上下文,但是如果有一个事务的话,它也可以在这个事务中运行 |
propagation_mandatory(xml文件中为mandatory) |
表示当前方法必须在一个事务中运行,如果没有事务,将抛出异常 |
propagation_nested(xml文件中为nested) |
表示如果当前方法正有一个事务在运行中,则该方法应该运行在一个嵌套事务中,被嵌套的事务可以独立于被封装的事务中进行提交或者回滚。如果封装事务存在,并且外层事务抛出异常回滚,那么内层事务必须回滚,反之,内层事务并不影响外层事务。如果封装事务不存在,则同propagation_required的一样 |
propagation_never(xml文件中为never) |
表示当方法务不应该在一个事务中运行,如果存在一个事务,则抛出异常 |
propagation_requires_new(xml文件中为requires_new) |
表示当前方法必须运行在它自己的事务中。一个新的事务将启动,而且如果有一个现有的事务在运行的话,则这个方法将在运行期被挂起,直到新的事务提交或者回滚才恢复执行。 |
propagation_not_supported(xml文件中为not_supported) |
表示该方法不应该在一个事务中运行。如果有一个事务正在运行,他将在运行期被挂起,直到这个事务提交或者回滚才恢复执行 |
隔离级别 |
含义 |
isolation_default |
使用数据库默认的事务隔离级别 |
isolation_read_uncommitted |
允许读取尚未提交的修改,可能导致脏读、幻读和不可重复读 |
isolation_read_committed |
允许从已经提交的事务读取,可防止脏读、但幻读,不可重复读仍然有可能发生 |
isolation_repeatable_read |
对相同字段的多次读取的结果是一致的,除非数据被当前事务自生修改。可防止脏读和不可重复读,但幻读仍有可能发生 |
isolation_serializable |
完全服从acid隔离原则,确保不发生脏读、不可重复读、和幻读,但执行效率最低。 |
Spring事务管理器的接口是org.springframework.transaction.PlatfromTransactionManager,如上图所示,Spring并不直接管理事务,
通过这个接口,Spring为各个平台如JDBC、Hibernate等都提供了对应的事务管理器,也就是将事务管理的职责委托给Hibernate或者JTA等持久化机制所提供的相关平台框架的事务来实现。
我们进入到 PlatformTransactionManager 接口,查看源码:
①、TransactionStatus getTransaction(TransactionDefinition definition) ,事务管理器 通过TransactionDefinition,获得“事务状态”,从而管理事务。
②、void commit(TransactionStatus status) 根据状态提交
③、void rollback(TransactionStatus status) 根据状态回滚
也就是说Spring事务管理的为不同的事务API提供一致的编程模型,具体的事务管理机制由对应各个平台去实现。
比如下面我们导入实现事务管理的两种平台:JDBC和Hibernate
然后我们再次查看PlatformTransactionManager接口,会发现它多了几个实现类,如下:
在上面 PlatformTransactionManager 接口中,有如下方法:
这个方法返回的是 TransactionStatus对象,然后程序根据返回的对象来获取事务状态,然后进行相应的操作。
而 TransactionStatus 这个接口的内容如下:
这个接口描述的是一些处理事务提供简单的控制事务执行和查询事务状态的方法,在回滚或提交的时候需要应用对应的事务状态
上面讲到的事务管理器接口PlatformTransactionManager通过getTransaction(TransactionDefinition definition)方法来得到事务,这个方法里面的参数是TransactionDefinition类,这个类就定义了一些基本的事务属性。
那么什么是事务属性呢?事务属性可以理解成事务的一些基本配置,描述了事务策略如何应用到方法上。事务属性包含了5个方面,如图所示:
TransactionDefinition 接口方法如下:
编程式事务处理:所谓编程式事务指的是通过编码方式实现事务,允许用户在代码中精确定义事务的边界。即类似于JDBC编程实现事务管理。管理使用TransactionTemplate或者直接使用底层的PlatformTransactionManager。对于编程式事务管理,spring推荐使用TransactionTemplate。
声明式事务处理:管理建立在AOP之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过基于@Transactional注解的方式),便可以将事务规则应用到业务逻辑中。
简单地说,编程式事务侵入到了业务代码里面,但是提供了更加详细的事务管理;而声明式事务由于基于AOP,所以既能起到事务管理的作用,又可以不影响业务代码的具体实现。
实体两个:分别是订单和商品
package com.thit.entity;
import java.util.Date;
//订单表
public class Order {
private String id;//订单id
private String productsId;//商品id
private int number;//购买数量
private double price;//价格
private Date createTime;//下单时间
private Date sendTime;//发单时间
private Date confirmTime;//确认收货时间
private String consignee;//收货人
private String consigneePhone;//收货人电话
private String consigneeAddress;//收货人地址
private String status;//状态
public Order() {
}
public Order(String id, String productsId, int number, double price, String consignee, String consigneePhone, String consigneeAddress) {
this.id = id;
this.productsId = productsId;
this.number = number;
this.price = price;
this.consignee = consignee;
this.consigneePhone = consigneePhone;
this.consigneeAddress = consigneeAddress;
}
// set get方法省略
}
dao和实现类两个
package com.thit.dao;
import java.util.List;
import com.thit.entity.Order;
public interface OrderDao {
void insert(Order order);
void update(Order order);
void delete(String id);
Order select(String id);
List select();
}
----实现类----
package com.thit.daoimpl;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import com.thit.dao.OrderDao;
import com.thit.entity.Order;
@Repository
public class OrderDaoImpl implements OrderDao {
@Autowired
private JdbcTemplate jdbcTemplate;
public void insert(Order order) {
// TODO Auto-generated method stub
String sql = "insert into orders values(?,?,?,?,?,?,?,?,?,?,?)";
jdbcTemplate.update(sql, order.getId(), order.getProductsId(), order.getNumber(), order.getPrice(),
order.getCreateTime(), order.getSendTime(), order.getConfirmTime(), order.getConsignee(),
order.getConsigneePhone(), order.getConsigneeAddress(), order.getStatus());
}
public void update(Order order) {
// TODO Auto-generated method stub
String sql = "update orders set create_time=?,send_time=?,confirm_time=?,consignee=?,consignee_phone=?,consignee_address=?,status=? where id=?";
jdbcTemplate.update(sql, order.getProductsId(), order.getNumber(), order.getPrice(), order.getCreateTime(),
order.getSendTime(), order.getConfirmTime(), order.getConsignee(), order.getConsigneePhone(),
order.getConsigneeAddress(), order.getStatus(), order.getId());
}
public void delete(String id) {
// TODO Auto-generated method stub
String sql = "delete from orders where id=?";
jdbcTemplate.update(sql, id);
}
public Order select(String id) {
// TODO Auto-generated method stub
String sql = "select form orders where id=?";
return jdbcTemplate.queryForObject(sql, new OrderRowMapper(), id);
}
public List select() {
// TODO Auto-generated method stub
String sql = "select * from orders";
return jdbcTemplate.query(sql, new OrderRowMapper());
}
public JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
}
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
private class OrderRowMapper implements RowMapper {
public Order mapRow(ResultSet resultSet, int rowNum) throws SQLException {
// TODO Auto-generated method stub
Order order = new Order();
order.setId(resultSet.getString("id"));
order.setProductsId(resultSet.getString("products_id"));
order.setNumber(resultSet.getInt("number"));
order.setPrice(resultSet.getDouble("price"));
order.setCreateTime(resultSet.getTimestamp("create_time"));
order.setSendTime(resultSet.getTimestamp("send_time"));
order.setConfirmTime(resultSet.getTimestamp("confirm_time"));
order.setConsignee(resultSet.getString("consignee"));
order.setConsigneePhone(resultSet.getString("consignee_phone"));
order.setConsigneeAddress(resultSet.getString("consignee_address"));
order.setStatus(resultSet.getString("status"));
return order;
}
}
}
package com.thit.dao;
import java.util.List;
import com.thit.entity.Product;
public interface ProductDao {
void insert(Product product);
void update(Product product);
void delete(String id);
Product select(String id);
List select();
}
-----实现类----
package com.thit.daoimpl;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import com.thit.dao.ProductDao;
import com.thit.entity.Product;
@Repository
public class ProductDaoImpl implements ProductDao {
//通过set方法自动注入
@Autowired
private JdbcTemplate jdbcTemplate;
public void insert(Product product) {
String sql = "insert into products values(?,?,?,?,?)";
jdbcTemplate.update(sql,product.getId(),product.getTitle(),product.getPrice(),product.getStock(),product.getStatus());
}
public void update(Product product) {
String sql = "update products set title=?,price=?,stock=?,status=? where id=?";
jdbcTemplate.update(sql,product.getTitle(),product.getPrice(),product.getStock(),product.getStatus(),product.getId());
}
public void delete(String id) {
// TODO Auto-generated method stub
String sql = "delete form products where id=?";
jdbcTemplate.update(sql);
}
public Product select(String id) {
String sql = "select * from products where id=?";
Product p=jdbcTemplate.queryForObject(sql, new RowMapper() {
public Product mapRow(ResultSet resultSet, int rowNum) throws SQLException {
// TODO Auto-generated method stub
Product product=new Product();
product.setId(resultSet.getString("id"));
product.setTitle(resultSet.getString("title"));
product.setPrice(resultSet.getDouble("price"));
product.setStock(resultSet.getInt("stock"));
product.setStatus(resultSet.getString("status"));
return product;
}
}, id);
return p;
}
public List select() {
// TODO Auto-generated method stub
String sql = "select * from products";
List list= jdbcTemplate.query(sql,new RowMapper() {
public Product mapRow(ResultSet resultSet, int rowNum) throws SQLException {
Product product=new Product();
product.setId(resultSet.getString("id"));
product.setTitle(resultSet.getString("title"));
product.setPrice(resultSet.getDouble("price"));
product.setStock(resultSet.getInt("stock"));
product.setStatus(resultSet.getString("status"));
return product;
}
});
return list;
}
public JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
}
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
}
service
package com.thit.service;
import com.thit.entity.Order;
public interface OrderService {
void addOrder(Order order);
}
公共配置文件:spring_dao.xml
根据不同的serviceImp来方案验证不同的结果
配置文件
代码实现类
package com.thit.serviceImpl;
import java.util.Date;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import com.thit.dao.OrderDao;
import com.thit.dao.ProductDao;
import com.thit.entity.Order;
import com.thit.entity.Product;
import com.thit.service.OrderService;
@Service(value="orderServiceimpl111")
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderDao orderDao;
@Autowired
private ProductDao productDao;
@Autowired
private PlatformTransactionManager transactionManager;
@Autowired
private TransactionDefinition transactionDefinition;
//private HibernateTransactionManager hibernateTransactionManager;
public void addOrder(Order order) {
// TODO Auto-generated method stub
//订单表
order.setCreateTime(new Date());
order.setStatus("待付款");
TransactionStatus status=null;
//开启事务
try {
TransactionStatus status=transactionManager.getTransaction(transactionDefinition);
//插入一条订单数据并且根据订单数据的下单数在商品表库存相对减少
orderDao.insert(order);
Product p=productDao.select(order.getProductsId());
p.setStock(p.getStock()-order.getNumber());
productDao.update(p);
//提交事务
transactionManager.commit(status);
} catch (Exception e) {
// TODO: handle exception
transactionManager.rollback(status);
e.printStackTrace();
}
}
}
配置文件:
代码实现:
package com.thit.serviceImpl;
import java.util.Date;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
import com.thit.dao.OrderDao;
import com.thit.dao.ProductDao;
import com.thit.entity.Order;
import com.thit.entity.Product;
import com.thit.service.OrderService;
@Service(value="orderServiceimpl2")
public class OrderServiceImpl2 implements OrderService {
@Autowired
private OrderDao orderDao;
@Autowired
private ProductDao productDao;
@Autowired
private TransactionTemplate template;
public void addOrder(final Order order) {
// TODO Auto-generated method stub
//订单表
System.out.println("进入");
order.setCreateTime(new Date());
order.setStatus("待付款测试2");
template.execute(new TransactionCallback
PROPAGATION_REQUIRED,readOnly
PROPAGATION_REQUIRED,readOnly
PROPAGATION_REQUIRED,readOnly
PROPAGATION_REQUIRED
Java代码:
package com.thit.serviceImpl;
import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
import com.thit.dao.OrderDao;
import com.thit.dao.ProductDao;
import com.thit.entity.Order;
import com.thit.entity.Product;
import com.thit.service.OrderService;
public class OrderServiceImpl3 implements OrderService {
@Autowired
private OrderDao orderDao;
@Autowired
private ProductDao productDao;
public void addOrder( Order order) {
// TODO Auto-generated method stub
// 订单表
System.out.println("进入");
order.setCreateTime(new Date());
order.setStatus("待付款测试2");
List list=orderDao.select();
System.out.println(list.size());
orderDao.insert(order);
// 商品
Product p = productDao.select(order.getProductsId());
p.setStock(p.getStock() - order.getNumber());
productDao.update(p);
}
}
编程事务不利于代码扩展,每次都需要手动开启事务,和代码耦合在一起,没有用到Spring的Aop思想
配置文件如下
Java代码:
public class OrderServiceImpl3 implements OrderService {
@Autowired
private OrderDao orderDao;
@Autowired
private ProductDao productDao;
//声明式事务代码简洁 第一种当时基于拦截器
public void addOrder( Order order) {
// TODO Auto-generated method stub
// 订单表
System.out.println("进入");
order.setCreateTime(new Date());
order.setStatus("待付款测试2");
List list=orderDao.select();
System.out.println(list.size());
orderDao.insert(order);
// 商品
Product p = productDao.select(order.getProductsId());
p.setStock(p.getStock() - order.getNumber());
productDao.update(p);
}
}
配置文件如下:
代码只需要添加
package com.thit.servicImpl;
import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.thit.dao.OrderDao;
import com.thit.dao.ProductDao;
import com.thit.entity.Order;
import com.thit.entity.Product;
import com.thit.service.OrderService;
@Service(value="OrderServiceImpl6")
public class OrderServiceImpl6 implements OrderService {
@Autowired
private OrderDao orderDao;
@Autowired
private ProductDao productDao;
//设置事务传播性和隔离级别
@Transactional(propagation=Propagation.REQUIRED,readOnly=false,isolation=Isolation.REPEATABLE_READ)
public void addOrder( Order order) {
// TODO Auto-generated method stub
// 订单表
System.out.println("进入");
order.setCreateTime(new Date());
order.setStatus("待付款测试2");
List list=orderDao.select();
System.out.println(list.size());
orderDao.insert(order);
// 商品
Product p = productDao.select(order.getProductsId());
p.setStock(p.getStock() - order.getNumber());
productDao.update(p);
}
}
测试代码如下:
package com.thit.test;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.thit.entity.Order;
import com.thit.servicImpl.OrderServiceImpl6;
import com.thit.service.OrderService;
import com.thit.serviceImpl.OrderServiceImpl;
import com.thit.serviceImpl.OrderServiceImpl2;
import com.thit.serviceImpl.OrderServiceImpl3;
public class test1 {
public static void main(String[] args) {
test1 t = new test1();
t.testAddOrder6();
}
// 基于底层API
public void testAddOrder() {
System.out.println("开始1132");
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring_service1.xml");
Order order = new Order("100023", "100002", 2, 1799, "", "", "测试1");
OrderServiceImpl orderServiceImpl = (OrderServiceImpl) applicationContext.getBean("orderServiceimpl111");
orderServiceImpl.addOrder(order);
}
// 基于transactiontemplate
public void testAddOrder1() {
System.out.println("开始");
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring_service2.xml");
Order order = new Order("100025", "100002", 2, 1799, "", "", "");
OrderServiceImpl2 orderServiceImpl = (OrderServiceImpl2) applicationContext.getBean("orderServiceimpl2");
orderServiceImpl.addOrder(order);
}
// 申明式事务,基于配置文件
public void testAddOrder3() {
System.out.println("开始3");
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring_service3.xml");
Order order = new Order("100035", "100002", 2, 1799, "", "", "申请式事务testAddOrder3()");
OrderServiceImpl3 orderServiceImpl = (OrderServiceImpl3) applicationContext.getBean("OrderServiceImpl3");
orderServiceImpl.addOrder(order);
}
// 申明式事务,基于配置文件
public void testAddOrder4() {
System.out.println("开始4");
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring_service4.xml");
Order order = new Order("100034", "100002", 2, 1799, "", "", "申请式事务testAddOrder4");
OrderServiceImpl3 orderServiceImpl = (OrderServiceImpl3) applicationContext.getBean("OrderServiceImpl3");
orderServiceImpl.addOrder(order);
}
// 申明式事务,基于配置文件
public void testAddOrder5() {
System.out.println("开始5");
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring_service5.xml");
Order order = new Order("100041", "100002", 2, 1799, "", "", "申请式事务testAddOrder5() ");
OrderServiceImpl3 orderServiceImpl = (OrderServiceImpl3) applicationContext.getBean("OrderServiceImpl5");
orderServiceImpl.addOrder(order);
}
// 申明式事务,基于配置文件
public void testAddOrder6() {
System.out.println("开始6");
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring_service6.xml");
Order order = new Order("100043", "100002", 2, 1799, "", "", "申请式事务testAddOrder5() ");
OrderService orderServiceImpl = (OrderService) applicationContext.getBean("OrderServiceImpl6");
orderServiceImpl.addOrder(order);
}
}
=========================================================================================================
项目目录结构
附录建表sql:
//订单表
create table orders
(
id char(6) not null COMMENT '编号',
products_id char(6) not null COMMENT '商品编号',
number int COMMENT '数量',
price double COMMENT '价格',
create_time datetime COMMENT '下单时间',
send_time datetime COMMENT '发货时间',
confirm_time datetime COMMENT '确认收货时间',
consignee varchar(20) COMMENT '收货人',
consignee_phone char(11) COMMENT '收货人电话',
consignee_address varchar(100) COMMENT '收货人地址',
status varchar(10) COMMENT '状态',
primary key (id)
);
//商品表
create table products
(
id char(6) not null COMMENT '商品id',
title varchar(20) COMMENT '商品名称',
price double COMMENT '价格',
stock int COMMENT '库存数',
status varchar(10) COMMENT '状态',
primary key (id)
);
insert into products values('100001','苹果',2,100,'正常');
insert into products values('100002','香蕉',5,100,'正常');
insert into products values('100003','橘子',5,100,'正常');
参考地址:https://www.cnblogs.com/ysocean/p/7617620.html#_label3