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. MySQL权限原理及删除MySQL的匿名账户

    MySQL权限系统的工作原理 MySQL权限系统通过下面两个阶段进行认证: (1)对连接的用户进行身份认证,合法的用户通过认证,不合法的用户拒绝连接: (2)对通过认证的合法用户赋予相应的权限,用户可 ...

  2. codeforce 1311 C. Perform the Combo 前缀和

    You want to perform the combo on your opponent in one popular fighting game. The combo is the string ...

  3. CodeForces - 1058A. In Search of an Easy Problem

    这题,全零是esay有1是hard,真难呀. #include<bits/stdc++.h> using namespace std; int main(){ int n,i,x,flag ...

  4. 题目分享L

    题意:n个人围成一个环,每个人初始有一些金币,每个人可以把金币递给相邻的人,问最少传递多少金币使每个人金币数相同? 分析:首先在保证最优的情况下不可能会出现相邻的两个人互相送金币,因为这样他们公共的部 ...

  5. RocketMQ搭建全过程

    RocketMQ下载地址:https://mirrors.tuna.tsinghua.edu.cn/apache/rocketmq/4.3.0/rocketmq-all-4.3.0-bin-relea ...

  6. Linux权限管理、系统进程管理

    权限管理 linux系统中分为四种角色 u=user 当前用户   g=group 同组用户   o=other 其他用户   a=all 代表所有用户 三种权限 r=read 可读 w=write ...

  7. CSS 块元素、内联元素、内联块元素三者的区别与转换

    三种元素 块元素 内联元素 内联块元素 元素之间的转换 三种元素 元素就是标签,布局中常用的有三种标签,块元素.内联元素.内联块元素. 了解这三种元素的特性,才能熟练的进行页面布局. 块元素 块元素, ...

  8. Golang 实现 Redis(5): 用跳表实现SortedSet

    本文是使用 golang 实现 redis 系列的第五篇, 将介绍如何使用跳表实现有序集合(SortedSet)的相关功能. 跳表(skiplist) 是 Redis 中 SortedSet 数据结构 ...

  9. 王颖奇 201771010129《面向对象程序设计(java)》第四周学习总结

    实验四 类与对象的定义及使用 实验时间 2018-9-20 1.目的与要求 学习目标 掌握类与对象的基础概念,理解类与对象的关系: 掌握对象与对象变量的关系: 掌握预定义类的基本使用方法,熟悉Math ...

  10. 物流配送中心管理系统(SSM+MYSQL)

    工程项目视频观看地址:www.toutiao.com/i6804066711… 本文首先对系统所涉及到的基础理论知识进行阐述,并在此基础上进行了系统分析.系统分析是平台开发的一个不可缺少的环节,为了能 ...