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 使用注解对事务控制详解与实例的更多相关文章

  1. 【Spring】——声明式事务配置详解

    项目中用到了spring的事务: @Transactional(rollbackFor = Exception.class, transactionManager = "zebraTrans ...

  2. spring事务管理(详解和实例)

    原文地址: 参考地址:https://blog.csdn.net/yuanlaishini2010/article/details/45792069 写这篇博客之前我首先读了<Spring in ...

  3. spring基于注解的事务控制

    pom配置: <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http ...

  4. Spring学习(十九)----- Spring的五种事务配置详解

    前段时间对Spring的事务配置做了比较深入的研究,在此之间对Spring的事务配置虽说也配置过,但是一直没有一个清楚的认识.通过这次的学习发觉Spring的事务配置只要把思路理清,还是比较好掌握的. ...

  5. django后台使用MySQL情况下的事务控制详解

    写在前面: 默认情况下django会把autocommit设置为“1”也就是说所针对数据库的每一次操作都会被做成“单独”的一个事务:这样的处理好处就在于它方便, 在编程的时候可以少写一些代码,比如我们 ...

  6. 注解@PostConstruct与@PreDestroy详解及实例

    Java EE5 引入了@PostConstruct和@PreDestroy这两个作用于Servlet生命周期的注解,实现Bean初始化之前和销毁之前的自定义操作.此文主要说明@PostConstru ...

  7. Java---JUnita、注解与类加载器详解以及实例

    JUnit软件测试技术(工具) 在项目中建立专门用户测试的包结构. 在Junit中,通过@Test注解,可以运行一个方法. ★ Junit注解说明 使用了@Test注解应该满足以下条件: 1) 必须是 ...

  8. (转)Spring事务管理详解

    背景:之前一直在学习数据库中的相关事务,而忽略了spring中的事务配置,在阿里面试时候基本是惨败,这里做一个总结. 可能是最漂亮的Spring事务管理详解 https://github.com/Sn ...

  9. 可能是最漂亮的Spring事务管理详解

    Java面试通关手册(Java学习指南):https://github.com/Snailclimb/Java_Guide 微信阅读地址链接:可能是最漂亮的Spring事务管理详解 事务概念回顾 什么 ...

随机推荐

  1. iOS9.2.1 App从AppStore上下载闪退问题

    首先这是小编的第一篇文章,我是一名做iOS开发的小白,出于爱好会更新发表些相关的技术文章,偶尔也会发些视频.恳请大家不要去嘲笑一个努力的人,要是做的不好请多多评论,反正我也不改. 好了!敲黑板!!说正 ...

  2. INTERVIEW #3

    菊厂的面试本来没打算记录,因为当时投的是非技术岗(技术支持).为了全面,就寥做记录. 菊厂的面试因为有口头保密协议,所以不能透露具体题目. 0 群面 简历通过筛选后,会有短信通知去面试. 非技术岗第一 ...

  3. 图论--最短路--SPFA

    SPFA算法(shortest path faster algorithm)算法是西南交通大学段凡丁于1994年发表的,它在Bellman-ford算法的基础上进行了改进,使其在能够处理待负权图的单元 ...

  4. 2019 ICPC 银川网络赛 H. Fight Against Monsters

    It is my great honour to introduce myself to you here. My name is Aloysius Benjy Cobweb Dartagnan Eg ...

  5. predixy源码学习--开篇

    最近开始研究predixy.predixy是一款高性能全功能redis代理 ,网上有的文章大部分都是功能上的介绍,很少有源码相关的分享. predixy的相关介绍在github: https://gi ...

  6. Java——枚举

    枚举类简介: Java5新增了一个enum关键字(它与class.interface关键字的地位相同),用以定义枚举类.枚举类也是一种特殊的类,所以也具有和类相同的变量和方法,也可以定义自己的构造器. ...

  7. DHCP报文(1)

    DHCP报文 1.地址申请类型(4步工作原理,常考) (1)此题是典型的四步工作原理,在其配置过程中由于没有分配IP地址,用的是广播形式,所以其4中报文类型的目的IP地址均为255.255.255.2 ...

  8. 如何优雅的使用Fegin去构造通用的服务调用的API

    第一步: 创建一个公共的API服务:命名为api(根据自己实际情况进行命名) <?xml version="1.0" encoding="UTF-8"?& ...

  9. 【HBase】底层原理

    目录 系统架构 表数据模型 物理存储 系统架构 在文章[HBase]基本介绍和基础架构中已经有简单介绍 Client -- 包含访问hbase的接口,client维护着一些cache来加快对hbase ...

  10. CF#633C Spy Syndrome 2 DP+二分+hash

    Spy Syndrome 2 题意 现在对某个英文句子,进行加密: 把所有的字母变成小写字母 把所有的单词反过来 去掉单词之间的空格 比如:Kira is childish and he hates ...