第2章 Spring编程式事务

2-1 编程式事务-1

第2章 Spring编程式事务_第1张图片

什么是事务?

第2章 Spring编程式事务_第2张图片

 对于spring jdbc我们如何进行事务控制呢?

 第2章 Spring编程式事务_第3张图片

 通过实际的代码学习如何事务管理器完成实物的提交或者回滚

公司入职10名新员工,将员工批量的导入员工表中,唯一的要求就是一次全部导入成功,要么什么都不做。

创建service包 业务逻辑

第2章 Spring编程式事务_第4张图片

第2章 Spring编程式事务_第5张图片 

批量导入方法

 

 第2章 Spring编程式事务_第6张图片

 配置,完成注入

 测试方法

植入service

 调用

第2章 Spring编程式事务_第7张图片 

 

 第2章 Spring编程式事务_第8张图片

 这里觉得程序写完了就大错特错了,因为对于这10个数据来说他们并不是在一个事务中完成的

为什么这么说打印下日志看一下

加入依赖

第2章 Spring编程式事务_第9张图片

 先删除增加的数据,重新执行

第2章 Spring编程式事务_第10张图片

 都是更新操作

 从数据源获取jdbc数据连接

 创建全新的连接

 在新的连接中去执行sql语句

 这一部分是完成了一条数据的新增部分

 每执行一次循环都会重复的产生这个日志

这就意味着,在刚才循环的过程中,顶层并不是使用一个数据库连接而是创建了10个数据库链接,完成了十次插入的操作,同时也进行了10次提交。这十条数据在各自的事务中并不是一个整体,我们期望的正确结果是这10次insert操作应该是在1个数据库连接中重复的去执行insert

第2章 Spring编程式事务_第11张图片

 

 

 我们的需求是 10条必须全部插入成功如果出现问题就什么都不做

如何解决?那就是引入事务进行整体判断

2-2 编程式事务-2

使用程序代码是手动控制什么时候提交?什么时候回滚?

编程式事务需要配置一个核心的对象

事务管理器

基于数据源的管理器,需要绑定一个数据源

 基于这个管理器就能完成对事物的整体提交和回滚

怎么用?

注入他 

 生成getset

回到xml的service中对他进行注入

 此时就具备的事务管理功能

 从这句以后所有数据的新增修改删除都会被直接放到事务区中由事务统一进行管理

 事务状态包含了当前方法所执行事务的目前阶段

成功

第2章 Spring编程式事务_第12张图片

 出现错误要进行捕捉,进行回滚,将运行时异常原封不动的抛出去

第2章 Spring编程式事务_第13张图片

运行

 

 抛出异常意味着要在事务中进行回滚

第2章 Spring编程式事务_第14张图片

 部分数据不再出现

底层原理

第2章 Spring编程式事务_第15张图片

 第二次循环并没有创建新的数据库连接,而是去应用原有的唯一的数据库连接

 第三次出现异常的时候 回滚

 增加后所有的数据库连接都是在一个中完成的,写入的数据并不是直接进入表中而是放到了事务区中,之后再根据方法是否执行成功,来提交或者回滚

 第2章 Spring编程式事务_第16张图片

 

 

频繁地使用去完成数据的新增

第2章 Spring编程式事务_第17张图片 

 

完成10次后 一次性提交写入

3-1 声明式事务配置

 编程式事务根据么个程序员的水平不同可能会出现遗忘事务控制的状况

第2章 Spring编程式事务_第18张图片

 第2章 Spring编程式事务_第19张图片

 

 第2章 Spring编程式事务_第20张图片

代码演示, 打开s02基础工程

不修改原始代码的情况下配置声明式事务

引入依赖

第2章 Spring编程式事务_第21张图片

 事务管理器

事务通知配置

额外增加一个命名空间url地址

 增加所对应描述文件xsd的地址

 aop命名空间

aop的xsd地址

 

第2章 Spring编程式事务_第22张图片

 说明事务通知作用在那些类上要确定通知范围

第2章 Spring编程式事务_第23张图片

 测试运行

第2章 Spring编程式事务_第24张图片

 第2章 Spring编程式事务_第25张图片

 

 第2章 Spring编程式事务_第26张图片

 

 成功第2章 Spring编程式事务_第27张图片

 又有一个新问题现在只有一个bacthImport,但是未来service上有各种各样的方法,难道要在

 定义成百上千个方法说明他是声明式事务吗其实不用

可以进行通配符映射batchImport可以写成

 不需要事务和写操作的方法

 与之类似的

其它选项,当前面几项都不符合要求时其他的情况是否开启声明式事务?

默认使用

 

不适用,根据情况而定

 

 3-2 自由编程

第2章 Spring编程式事务_第28张图片

 答案

package com.imooc.spring.jdbc.dao;
 
import com.imooc.spring.jdbc.entity.Hotel;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
 
import java.util.List;
 
public class HotelDao {
   private JdbcTemplate jdbcTemplate;
   public Hotel findById(Integer OrderNo){
       String sql="select* from hotel where OrderNo=?";
       Hotel hotel = jdbcTemplate.queryForObject(sql, new Object[]{OrderNo}, new BeanPropertyRowMapper(Hotel.class));
       return hotel;
 
   }
   public List  findByCity(String city){
       String sql="select * from hotel where city=?";
       List list = jdbcTemplate.query(sql, new Object[]{city}, new BeanPropertyRowMapper(Hotel.class));
       return list;
 
   }
   public int insert(Hotel hotel){
       String sql="insert into hotel(orderNo,city,price,hotelName,arriveDate,leaveDate)values(?,?,?,?,?,?)";
       int i = jdbcTemplate.update(sql, new Object[]{hotel.getOrderNo(), hotel.getCity(), hotel.getPrice(), hotel.getHotelName(), hotel.getArriveDate(), hotel.getLeaveDate()});
 
       return i;
   }
   public int alter(Hotel hotel){
       String sql="update hotel set city=?,price=?,hotelName=?,arriveDate=?,leaveDate=? where orderNO=? ";
       int count = jdbcTemplate.update(sql, new Object[]{hotel.getCity(), hotel.getPrice(), hotel.getHotelName(),hotel.getArriveDate(), hotel.getLeaveDate(),hotel.getOrderNo()});
       return count;
   }
   public  int delete(Integer integer){
       String sql="delete from hotel where orderNo=?";
       int count = jdbcTemplate.update(sql, new Object[]{integer});
       return count;
 
   }
 
 
    public JdbcTemplate getJdbcTemplate() {
        return jdbcTemplate;
    }
 
    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }
}
package com.imooc.spring.jdbc.entity;
 
import java.util.Date;
 
public class Hotel {
    private Integer orderNo;
    private String city;
    private Float price;
    private String hotelName;
    private Date arriveDate;
    private Date leaveDate;
 
    @Override
    public String toString() {
        return "Hotel{" +
                "orderNo=" + orderNo +
                ", city='" + city + '\'' +
                ", price=" + price +
                ", hotelName='" + hotelName + '\'' +
                ", arriveDate=" + arriveDate +
                ", leaveDate=" + leaveDate +
                '}';
    }
 
    public Integer getOrderNo() {
        return orderNo;
    }
 
    public void setOrderNo(Integer orderNo) {
        this.orderNo = orderNo;
    }
 
    public String getCity() {
        return city;
    }
 
    public void setCity(String city) {
        this.city = city;
    }
 
    public Float getPrice() {
        return price;
    }
 
    public void setPrice(Float price) {
        this.price = price;
    }
 
    public String getHotelName() {
        return hotelName;
    }
 
    public void setHotelName(String hotelName) {
        this.hotelName = hotelName;
    }
 
    public Date getArriveDate() {
        return arriveDate;
    }
 
    public void setArriveDate(Date arriveDate) {
        this.arriveDate = arriveDate;
    }
 
    public Date getLeaveDate() {
        return leaveDate;
    }
 
    public void setLeaveDate(Date leaveDate) {
        this.leaveDate = leaveDate;
    }
}
package com.imooc.spring.jdbc.service;
 
import com.imooc.spring.jdbc.dao.HotelDao;
import com.imooc.spring.jdbc.entity.Hotel;
 
import java.util.Date;
 
public class HotelService {
    private HotelDao hotelDao;
    public  void batchImport(){
     for (int i=1;i<=5;i++){
         if (i==3){
             throw new RuntimeException();
         }
         Hotel hotel=new Hotel();
         hotel.setOrderNo(100+i);
         hotel.setCity("长沙");
         hotel.setHotelName("酒店8"+i);
         hotel.setArriveDate(new Date());
         hotel.setLeaveDate(new Date());
         hotel.setPrice(999.98f+i);
         hotelDao.insert(hotel);
     }
    }
 
    public HotelDao getHotelDao() {
        return hotelDao;
    }
 
    public void setHotelDao(HotelDao hotelDao) {
        this.hotelDao = hotelDao;
    }
}


 
    

    
    
    
    
    

    
        
    
    
        
            
        
    
    
        
        
    
    

    
    
        
        
    
    
        
 
        
    

import com.imooc.spring.jdbc.dao.HotelDao;
import com.imooc.spring.jdbc.entity.Hotel;
import com.imooc.spring.jdbc.service.HotelService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 
import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
 
import java.util.Date;
import java.util.List;
 
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:applicationContext.xml"})
public class JdbcTemplateTestor {
    @Resource
    private HotelService hotelService;
    @Resource
    private HotelDao hotelDao;
    @Test
    public void testFindById(){
        Hotel hotel = hotelDao.findById(10001);
        System.out.println(hotel);
 
    }
    @Test
    public void testFindByName(){
        List 上海 = hotelDao.findByCity("上海");
        System.out.println(上海);
 
    }
    @Test
    public  void testInsert(){
        Hotel hotel=new Hotel();
        hotel.setOrderNo(10099);
        hotel.setCity("长沙");
        hotel.setHotelName("酒店8");
        hotel.setArriveDate(new Date());
        hotel.setLeaveDate(new Date());
        hotel.setPrice(999.98f);
        int count = hotelDao.insert(hotel);
        System.out.println(count);
    }
    @Test
    public void testUpdate() throws ParseException {
        String date1="2020-4-30";
        String data2="2020-5-05";
        SimpleDateFormat simpleDateFormat =new SimpleDateFormat("yyyy-MM-dd");
        Hotel hotel = hotelDao.findById(10003);
        hotel.setLeaveDate(simpleDateFormat.parse(date1));
        hotel.setArriveDate(simpleDateFormat.parse(data2));
        int count = hotelDao.alter(hotel);
        System.out.println(count);
    }
    @Test
    public  void testDelete(){
        int count = hotelDao.delete(10099);
        System.out.println(count);
    }
    @Test
    public  void testBatchImport(){
        hotelService.batchImport();
        System.out.println("批量插入成功");
 
    }
    }

3-3 事务传播方式

第2章 Spring编程式事务_第29张图片

 第2章 Spring编程式事务_第30张图片

 通过案例了解

 propagation会为我们带来那些特性

还需要开发大量类似于batchimport的方法怎么办呢?

第2章 Spring编程式事务_第31张图片

 第2章 Spring编程式事务_第32张图片

依赖于

 

第2章 Spring编程式事务_第33张图片 

 第2章 Spring编程式事务_第34张图片

 新增一个方法

 增加bean

 

 

 第2章 Spring编程式事务_第35张图片

 测试

第2章 Spring编程式事务_第36张图片

 插入成功

第2章 Spring编程式事务_第37张图片

 作为当前代码是事物的嵌套使用

 默认也是开启声明式事务的

第2章 Spring编程式事务_第38张图片

 

 当前的配置是有问题的

作为批量导入,这两个方法之间应该是互不影响的但是employeeservice却做不到这个职责

演示一下

第2章 Spring编程式事务_第39张图片

 

数据没有插入成功

第2章 Spring编程式事务_第40张图片

import1插入成功就应该插入,但实际结果却不是这样

第2章 Spring编程式事务_第41张图片

 第2章 Spring编程式事务_第42张图片

 startImportJob在运行时会创造一个事物,而内侧嵌套调用的importjob1和importjob2因为配置的也是required内测执行时发现外侧已经有现成的事务了,所以job1的事务就会加入到外侧事务当中,也就是说整体是在一个事务中完成数据的增删改操作

第2章 Spring编程式事务_第43张图片

 要是这两个方法相对于start方法独立该怎么做呢?

 针对这两个方法在运行的过程中都会产生新的事务来自进行处理

更改后执行

第2章 Spring编程式事务_第44张图片

 第2章 Spring编程式事务_第45张图片

 数据就产生了

 

 第2章 Spring编程式事务_第46张图片

 3-4 选择练习

 第2章 Spring编程式事务_第47张图片

 

 3-5注解形式声明事务

 注解改造

设置扫描的基本包

 定义数据源

 针对系统底层公用类还是要自己增加bean来进行实例化

还要定义事务管理器 

 注解来完成对象实例化

 完成对象的注入

 

 测试一下

第2章 Spring编程式事务_第48张图片

 第2章 Spring编程式事务_第49张图片

 第2章 Spring编程式事务_第50张图片

 下面把关注点放在事务控制上,作为声明式事务如果利用注解非常的简单,全程只有一个注解

 测试

第2章 Spring编程式事务_第51张图片

 事务被成功地回滚了

 对应于不同的方法也可以单独设置

在这个查询方法上去应用声明式事务是无效的

进行单独设置采用非事务方式

 那么会优先利用这个方式其他的方法默认使用在类上的配置

 针对batchservice来进行一下设置,import方法都是可以独立的在方法中运行

第2章 Spring编程式事务_第52张图片

 

 在方法上也可以设置默认值,不需要使用事务 

 测试,能否将前半部分成功的导入 

第2章 Spring编程式事务_第53张图片

第2章 Spring编程式事务_第54张图片 

 第2章 Spring编程式事务_第55张图片

 3-6 自由编程

第2章 Spring编程式事务_第56张图片

 

你可能感兴趣的:(Spring,JDBC,与事务管理,spring,java,数据库)