Spring 使用注解对事务控制详解与实例
1.什么是事务
一荣俱荣,一损俱损,很多复杂的操作我们可以把它看成是一个整体,要么同时成功,要么同时失败。
事务的四个特征ACID:
原子性(Atomic):表示组成一个事务的多个数据库的操作的不可分割的单元,只有所有的操作成功才算成功,整个事务提交,其中任何一个操作失败了都是导致整个所有操作失败,事务会回滚。
一致性(Consistentcy):事务操作成功后,数据库所处的状态和业务规则一致。如果A账户给B账户汇100,A账户减去100,B加上100,两个账户的总额是不变的。
隔离性(islation):在多个数据库的操作相同的数据并发时,不同的事务有自己的数据空间,事务与事务之间不受干扰(不是绝对的)。干扰程度受数据库或者操作事务的隔离级别来决定,隔离级别越高,干扰就越低,数据的一致性越好,并发性就越差。
持久性(Druability):一旦事务提交成功,数据就被持久化到数据库,不可以回滚。
2.spring使用注解对事务的控制
Spring 事务管理有两种方式:编程式事务管理、声明式事务管理
编程式事务管理通过TransactionTemplate手动管理事务,在实际应用中很少使用,我们来重点学习声明式事务管理
声明式事务管理有三种实现方式:基于TransactionProxyFactoryBean的方式、基于AspectJ的XML方式、基于注解的方式
1. 新建一个java工程——导入spring 和事务管理所需要的jar ——然后选择全部jar 右键Build path ——最后如图 (我的java版本jre是1.8) Spring事务需要的jar
2.在src目录下新建5个包 如图
dao :数据连接层,主要用于存放对数据进行操作的类
model:模型层,主要用于存放实体类
service:服务层,主要用于对数据连接层进行操作的一些服务类。
util:工具类,主要用于存储工具方法
test:用于测试类
3.在dao数据连接层,建立里与数据库操作的类与对应的接口 (Order 订单 ,detail订单明细)
3.1 定义detailDao接口 代码如下:
package com.spring.dao; import com.spring.model.Detail;
import com.spring.model.Order; public interface detailDao {
//保存订单明细
public void saveDetail(Detail detail); }
3.2 定义OrderDao接口 代码如下:
package com.spring.dao; import com.spring.model.Order; public interface OrderDao {
//保存订单
public void saveOrder(Order order); }
3.3 实现以上接口
detailDaoImp 代码如下:
package com.spring.dao; import javax.sql.DataSource; import org.springframework.jdbc.core.JdbcTemplate; import com.spring.model.Detail;
import com.spring.model.Order; public class detailDaoImp implements detailDao { private DataSource dataSource;
private JdbcTemplate jdbcTemplate; public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
//保存订单明细
public void saveDetail(Detail detail) {
String SQL = "insert into t_detail values(null,?,?,?))";
jdbcTemplate.update(SQL, new Object[] { detail.getItemName(),detail.getQuantity(),detail.getOrderId() });
System.out.println("Insert detail success!");
} }
OrderDaoImp代码如下:
package com.spring.dao; import javax.sql.DataSource; import org.springframework.jdbc.core.JdbcTemplate; import com.spring.model.Order; public class OrderDaoImp implements OrderDao { private DataSource dataSource;
private JdbcTemplate jdbcTemplate; public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
//插入订单
public void saveOrder(Order order) {
String SQL = "insert into t_order values (null,?)";
System.out.println(SQL);
System.out.println(order.getTotal_price());
jdbcTemplate.update(SQL, new Object[]{order.getTotal_price()});
System.out.println("Insert order success!");
} }
4.在model层中新建两个实体类 (Order订单类,detail订单明细类)
Order订单类代码如下:
package com.spring.model; /*
* 订单表
*/
public class Order {
//订单编号
private Integer order_id;
//订单总金额
private Integer total_price;
public Integer getOrder_id() {
return order_id;
}
public void setOrder_id(Integer order_id) {
this.order_id = order_id;
}
public Integer getTotal_price() {
return total_price;
}
public void setTotal_price(Integer total_price) {
this.total_price = total_price;
}
}
detail订单明细类代码如下:
package com.spring.model; /**
* 商品明细表
* @author Administrator
*
*/
public class Detail {
//ID
private Integer detailId;
//外键 暂时可以忽略
private Integer orderId;
public Integer getDetailId() {
return detailId;
}
public void setDetailId(Integer detailId) {
this.detailId = detailId;
}
public Integer getOrderId() {
return orderId;
}
public void setOrderId(Integer orderId) {
this.orderId = orderId;
}
public Integer getQuantity() {
return quantity;
}
public void setQuantity(Integer quantity) {
this.quantity = quantity;
}
public String getItemName() {
return itemName;
}
public void setItemName(String itemName) {
this.itemName = itemName;
}
//商品数量
private Integer quantity;
//商品数量
private String itemName; }
5.在service中定义一个接口并且实现它
OrderService代码如下:
package com.spring.service; import com.spring.model.Detail;
import com.spring.model.Order; public interface OrderService {
//插入订单和订单明细
public void saveOrderAndDetail(Order order,Detail detail);
}
OrderServiceImp代码如下:
package com.spring.service; import org.springframework.transaction.annotation.Transactional; import com.spring.dao.OrderDaoImp;
import com.spring.dao.detailDaoImp;
import com.spring.model.Detail;
import com.spring.model.Order; /**
* 服务层 使用注解来实现事务管理
*
* @author Administrator
*
*/ public class OrderServiceImp implements OrderService {
// 注入两个对象
public OrderDaoImp OrderDaoImp; public detailDaoImp detailDaoImp; @Transactional
@Override
// 如果加上@Transaction时,方法执行有异常,整个事务数据都会回滚,数据库中不会存在有数据。
public void saveOrderAndDetail(Order order, Detail detail) {
OrderDaoImp.saveOrder(order);
/**
* 如果不加@transaction时有异常存在,OrderDaoImp.saveOrder(order)方法将会执行。
* 但detailDaoImp.saveDetail(detail)不会执行
**/
int i = 100 / 0;
detailDaoImp.saveDetail(detail); } public OrderDaoImp getOrderDaoImp() {
return OrderDaoImp;
} public void setOrderDaoImp(OrderDaoImp orderDaoImp) {
OrderDaoImp = orderDaoImp;
} public detailDaoImp getDetailDaoImp() {
return detailDaoImp;
} public void setDetailDaoImp(detailDaoImp detailDaoImp) {
this.detailDaoImp = detailDaoImp;
} }
6.在util包中定义一个通知方法类
package com.spring.util; public class SeizedAdvice {
/**
* 定义通知
*/ public void beforeAdvice(){
System.out.println("——————我是前置通知————————"); }
public void afterAdvice(){
System.out.println("------我是后置通知-------"); }
public void afterReturningAdvice(Object object){
System.out.println("————————我是返回后通知——————————"+object.toString()); }
public void afterThrowingAdvice(IllegalAccessError illegalAccessError){
System.out.println("--------我是异常返回异常返回通知---------"+illegalAccessError.toString()); } }
7.在test中定义个测试类,用于测试
package com.test; import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import com.spring.model.Detail;
import com.spring.model.Order;
import com.spring.service.OrderServiceImp; public class Test { public static void main(String[] args) {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("bean.xml");
OrderServiceImp imp=(OrderServiceImp)applicationContext.getBean("OrderServiceImp"); Order order=new Order();
order.setTotal_price(699);
Detail detail=new Detail();
detail.setItemName("牙刷");
detail.setQuantity(3);
detail.setOrderId(4);
imp.saveOrderAndDetail(order,detail); }
}
8.最后就是我们的配置文件和数据库中的两张表
Spring bean.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: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-4.3.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
<!-- 定义数据源 -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/jerry" />
<property name="username" value="root" />
<property name="password" value="1234" />
</bean> <!-- 事务管理方式注解驱动 -->
<tx:annotation-driven transaction-manager="transactionManager" /> <!-- 配置数据 proxy-target-class属性值决定是基于接口的还是基于类的代理被创建。
如果proxy-target-class 属性值被设置为true,那么基于类的代理将起作用-->
<aop:config proxy-target-class="true">
<!-- 切 面-->
<aop:aspect id="myAspect" ref="SeizedAdvice">
<!-- 切 点-->
<aop:pointcut expression="execution(* com.spring.service.OrderServiceImp.*(..))"
id="myPointCut" />
<aop:before pointcut-ref="myPointCut" method="beforeAdvice" />
<aop:after pointcut-ref="myPointCut" method="afterAdvice" />
</aop:aspect>
</aop:config> <!-- 定义事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean> <!-- 定义我们所需的bean -->
<bean id="SeizedAdvice" class="com.spring.util.SeizedAdvice"></bean> <bean id="OrderServiceImp" class="com.spring.service.OrderServiceImp">
<property name="detailDaoImp" ref="detailDaoImp"></property>
<property name="OrderDaoImp" ref="OrderDaoImp"></property>
</bean> <bean id="detailDaoImp" class="com.spring.dao.detailDaoImp">
<property name="dataSource" ref="dataSource" />
</bean> <bean id="OrderDaoImp" class="com.spring.dao.OrderDaoImp">
<property name="dataSource" ref="dataSource" />
</bean> </beans>
9. 数据库设计
detail(订单明细表 detail_id 订单明细ID,item_name 商品名称,quantity 订单数量 ,order_id 外键 暂时不用管这个属性)
Order(订单表,order_id 订单id,total_price 总金额)
10. 没有加@transaction测试如下:
这就会造成数据错误,不符合事务管理要求。加上@transaction再次测试如下图;
Spring 使用注解对事务控制详解与实例的更多相关文章
- 【Spring】——声明式事务配置详解
项目中用到了spring的事务: @Transactional(rollbackFor = Exception.class, transactionManager = "zebraTrans ...
- spring事务管理(详解和实例)
原文地址: 参考地址:https://blog.csdn.net/yuanlaishini2010/article/details/45792069 写这篇博客之前我首先读了<Spring in ...
- spring基于注解的事务控制
pom配置: <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http ...
- Spring学习(十九)----- Spring的五种事务配置详解
前段时间对Spring的事务配置做了比较深入的研究,在此之间对Spring的事务配置虽说也配置过,但是一直没有一个清楚的认识.通过这次的学习发觉Spring的事务配置只要把思路理清,还是比较好掌握的. ...
- django后台使用MySQL情况下的事务控制详解
写在前面: 默认情况下django会把autocommit设置为“1”也就是说所针对数据库的每一次操作都会被做成“单独”的一个事务:这样的处理好处就在于它方便, 在编程的时候可以少写一些代码,比如我们 ...
- 注解@PostConstruct与@PreDestroy详解及实例
Java EE5 引入了@PostConstruct和@PreDestroy这两个作用于Servlet生命周期的注解,实现Bean初始化之前和销毁之前的自定义操作.此文主要说明@PostConstru ...
- Java---JUnita、注解与类加载器详解以及实例
JUnit软件测试技术(工具) 在项目中建立专门用户测试的包结构. 在Junit中,通过@Test注解,可以运行一个方法. ★ Junit注解说明 使用了@Test注解应该满足以下条件: 1) 必须是 ...
- (转)Spring事务管理详解
背景:之前一直在学习数据库中的相关事务,而忽略了spring中的事务配置,在阿里面试时候基本是惨败,这里做一个总结. 可能是最漂亮的Spring事务管理详解 https://github.com/Sn ...
- 可能是最漂亮的Spring事务管理详解
Java面试通关手册(Java学习指南):https://github.com/Snailclimb/Java_Guide 微信阅读地址链接:可能是最漂亮的Spring事务管理详解 事务概念回顾 什么 ...
随机推荐
- Struts2深入之动态调用Action
使用过Struts2的小伙伴们应该知道当我们的action的方法过多是如果需要通过Struts2框架进行运行,我们就必须在Struts2的配置文件Struts2.xml文件中配置多个action属性标 ...
- rabbitMQ消息队列原理
MQ:Message Queue,消息队列,是一种应用程序对应用程序的通信方法:应用程序通过读写出入队列的消息(针对应用程序的数据)来通信,而无需专用连接来链接它们. 1 rabbitMQ入 ...
- Chrome最新版如何安装Proxy SwitchyOmega
由于Chrome的代理设置与windows10的1703及以后的版本不兼容,导致无法使用代理功能,给工作带来了很大的不便.最近发现一款不错的Chrome代理插件Proxy SwitchyOmega,由 ...
- 实战-MySQL定时增量备份(2)
概要 引言 增量备份 恢复增量备份 定时备份 引言 在产品上线之后,我们的数据是相当重要的,容不得半点闪失,应该做好万全的准备,搞不好哪一天被黑客入侵或者恶意删除,那就 gg 了.所以要对我们的线上数 ...
- Codeforce 322E Ciel the Commander (点分治)
E. Ciel the Commander Now Fox Ciel becomes a commander of Tree Land. Tree Land, like its name said, ...
- Nmon 监控性能分析
一.CPU 信息 1.折线图中蓝线为 cpu 占有率变化情况:粉线为磁盘 IO 的变化情况: 2.下面表各种左边的位磁盘的总体数据,包括如下几个: Avg tps during an interval ...
- 全面解读 vue3.0
在此附上链接,在知乎上看到的,感觉说的很详细 https://zhuanlan.zhihu.com/p/46269528
- 软件——IDEA主题美化
前言 IntelliJ IDEA主要用于支持 Java.Scala.Groovy 等语言的开发工具,同时具备支持目前主流的技术和框架,擅长于企业应用.移动应用和 Web 应用的开发. IntelliJ ...
- K - Leapin' Lizards HDU - 2732 网络流
题目链接:https://vjudge.net/contest/299467#problem/K 这个题目从数据范围来看可以发现是网络流,怎么建图呢?这个其实不是特别难,主要是读题难. 这个建图就是把 ...
- 图形学_Bezier曲线
Bezier曲线由n个控制点生成,举个例子:当n=2时,点$P_0$.$P_1$之间遵从计算: $P_0=(1-t)P_0+tP_1$ 而推广为n维时,有: $P^n_0=(1-t)P^{n-1}_0 ...