spring5 JdbcTemplate+事务(尚硅谷学习笔记)

spring5 JdbcTemplate+事务(尚硅谷学习笔记)

JdbcTemplate(概念和准备)

  1. 什么是JdbcTemplate

    (1)Spring 框架对JDBC进行封装,使用JdbcTemplate方便实现对数据库的操作

  2. 准备工作

    (1)引入相关jar包

    • druid-1.1.9.jar
    • spring-jdbc-5.2.6.RELEASE.jar
    • mysql-connector-java-5.1.7-bin.jar
    • spring-orm-5.2.6.RELEASE.jar
    • spring-tx-5.2.6.RELEASE.jar

    (2)在spring文件配置数据库连接池

      <!-- 配置连接池 -->
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
              destroy-method="close">
            <property name="url" value="jdbc:mysql:///user_db" />
            <property name="username" value="root" />
            <property name="password" value="wrm200146" />
            <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        </bean>
    

    (3)配置JdbcTemlate对象,注入DataSource

      <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <!--    注入dateSource-->
            <property name="dataSource" ref="dataSource"></property>
         </bean>
    

    (4)创建service类,创建dao类,在dao注入jdbcTemolate对象

    (1)配置文件中

    • bean

      <!--    开启组件的扫描-->
          <context:component-scan base-package="com.atguigu"></context:component-scan>
      
    • service

      package com.atguigu.spring5.service;
      
      import com.atguigu.spring5.dao.BookDao;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.stereotype.Service;
      
      @Service
      public class BookService {
          //注入dao
          @Autowired
          private BookDao bookDao;
      
      }
      
      
    • Dao

      package com.atguigu.spring5.dao;
      
      
      public interface BookDao {
      }
      
      
      package com.atguigu.spring5.dao;
      
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.jdbc.core.JdbcTemplate;
      import org.springframework.stereotype.Repository;
      
      @Repository
      public class BookDaoImpl  implements BookDao{
              //注入JdbcTemplate
          @Autowired
          private JdbcTemplate jdbcTemplate;
      
      }
      

JdbcTemplate操作数据库(添加)

  1. 对应数据库创建一个实体类

    package com.atguigu.spring5.entity;
    
    public class User {
        private  String userId;
        private  String username;
        private  String ustatus;
    
        public String getUserId() {
            return userId;
        }
    
        public void setUserId(String userId) {
            this.userId = userId;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getUstatus() {
            return ustatus;
        }
    
        public void setUstatus(String ustatus) {
            this.ustatus = ustatus;
        }
    }
    
    
  2. 编写service和dao

    (1)在dao进行数据库添加操作

    (2)调用JdbcTemplate对象里面update方法实现添加操作

    update(String sql,Object... args)
    
    • 有两个参数

    • 第一个参数,sql语句

    • 第二个参数,可变参数,设置sql语句值

      package com.atguigu.spring5.dao;
      
      import com.atguigu.spring5.entity.Book;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.jdbc.core.JdbcTemplate;
      import org.springframework.stereotype.Repository;
      
      @Repository
      public class BookDaoImpl  implements BookDao{
              //注入JdbcTemplate
          @Autowired
          private JdbcTemplate jdbcTemplate;
      
          @Override
          public void add(Book book) {
              String sql="insert into t_book values(?,?,?)";
              int update =jdbcTemplate.update(sql,book.getUserId(),book.getUserId(),book.getUsername());
              System.out.println(update);
          }
      }
      
      

JdbcTemplate操作数据库(查询返回对象)

  1. JdbcTemplate 实现查询返回对象

    quueryForObject(String sql,RowMapper<T> rowmapper,Object.. args)
    
  2. 有三个参数

    • 第一个参数:sql 语句

    • 第二个参数:RowMapper 是接口,针对返回不同类型数据,使用这个接口里面实现类完成 数据封装

    • 第三个参数:sql 语句值

      /查询返回集合
      @Override
      public List<Book> findAllBook() {
       String sql = "select * from t_book";
       //调用方法
       List<Book> bookList = jdbcTemplate.query(sql, new
      BeanPropertyRowMapper<Book>(Book.class));
       return bookList
      

JdbcTemplate操作数据库(查询返回集合)

  • 场景:查询图书列表分页
  1. 调用JdbcTemplate 实现查询返回集合

    quuery(String sql,RowMapper<T> rowmapper,Object.. args)
    
  2. 有三个参数

    • 第一个参数:sql 语句

    • 第二个参数:RowMapper 是接口,针对返回不同类型数据,使用这个接口里面实现类完成 数据封装

    • 第三个参数:sql 语句值

      /查询返回集合
      @Override
      public List<Book> findAllBook() {
       String sql = "select * from t_book";
       //调用方法
       List<Book> bookList = jdbcTemplate.query(sql, new
      BeanPropertyRowMapper<Book>(Book.class));
       return bookList
      

JdbcTemplate操作数据库(批量操作)

  1. 批量操作:操作表里面多条记录

  2. JdbcTemplate 实现批量添加操作

    jdbcTemplate.batchUpdate(String sql,List<object[]> batchArs ) 
    
    • 有两个参数
    • 第一个参数:sql 语句
    • 第二个参数:List 集合,添加多条记录数据
    @Override
    public void batchAddBook(List<Object[]> batchArgs) {
     String sql = "insert into t_book values(?,?,?)";
     int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);
     System.out.println(Arrays.toString(ints));
    }
    //批量添加测试
    List<Object[]> batchArgs = new ArrayList<>();
    Object[] o1 = {"3","java","a"};
    Object[] o2 = {"4","c++","b"};
    Object[] o3 = {"5","MySQL","c"};
    batchArgs.add(o1);
    batchArgs.add(o2);
    batchArgs.add(o3);
    //调用批量添加
    bookService.batchAdd(batchArgs);
    
  3. JdbcTemplate 实现批量修改操作

    jdbcTemplate.batchUpdate(String sql,List<object[]> batchArs ) 
    
    • 有两个参数
    • 第一个参数:sql 语句
    • 第二个参数:List 集合,添加多条记录数据
    @Override
    public void batchAddBook(List<Object[]> batchArgs) {
     String sql = "insert into t_book values(?,?,?)";
     int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);
     System.out.println(Arrays.toString(ints));
    }
    //批量添加测试
    List<Object[]> batchArgs = new ArrayList<>();
    Object[] o1 = {"3","java","a"};
    Object[] o2 = {"4","c++","b"};
    Object[] o3 = {"5","MySQL","c"};
    batchArgs.add(o1);
    batchArgs.add(o2);
    batchArgs.add(o3);
    //调用批量添加
    bookService.batchAdd(batchArgs);
    
  4. JdbcTemplate 实现批量删除操作

    //批量删除
    @Override
    public void batchDeleteBook(List<Object[]> batchArgs) {
     String sql = "delete from t_book where user_id=?";
     int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);
     System.out.println(Arrays.toString(ints));
    }
    //批量删除
    List<Object[]> batchArgs = new ArrayList<>();
    Object[] o1 = {"3"};
    Object[] o2 = {"4"};
    batchArgs.add(o1);
    batchArgs.add(o2);
    //调用方法实现批量删除
    bookService.batchDelete(batchArgs);
    
    

事务操作(事务概念)

  1. 什么是事务

    (1)事务是数据库操作最基本单元,逻辑上一组操作,要么都成功,如果有一个失败所以的操作都失败

    (2)典型场景:银行转账

    • Lucy转账100元钱给mary
    • lucy少100,mary多100;
  2. 事务四个特性(ACID)

    (1)原子性

    (2)一致性

    (3)隔离性

    (4)持久性

事务操作(搭建事务操作环境)

  1. 创建数据库表,添加记录

    创建表 t_account 列名分别为 "id" ,"username","moeny"
    
    "id" "username"	"moeny"
    "1"	 "lucy"	    "1000"
    "2"  "mary"	    "1000"
    
  2. 创建 service,搭建 dao,完成对象创建和注入关系

    (1)service 注入 dao,在 dao 注入 JdbcTemplate,在 JdbcTemplate 注入 DataSource

    @Service
    public class UserService {
     //注入 dao
     @Autowired
     private UserDao userDao;
    }
    @Repository
    public class UserDaoImpl implements UserDao {
     @Autowired
     private JdbcTemplate jdbcTemplate;
    }
    
  3. 在 dao 创建两个方法:多钱和少钱的方法,在 service 创建方法(转账的方法)

    @Repository
    public class UserDaoImpl implements UserDao {
     @Autowired
     private JdbcTemplate jdbcTemplate;
     //lucy 转账 100 给 mary
     //少钱
     @Override
     public void reduceMoney() {
     String sql = "update t_account set money=money-? where username=?";
     jdbcTemplate.update(sql,100,"lucy");
     }
     //多钱
     @Override
     public void addMoney() {
     String sql = "update t_account set money=money+? where username=?";
     jdbcTemplate.update(sql,100,"mary");
     }
    }
    @Service
    public class UserService {
     //注入 dao
     @Autowired
     private UserDao userDao;
     //转账的方法
     public void accountMoney() {
     //lucy 少 100
     userDao.reduceMoney();
     //mary 多 100
     userDao.addMoney();
     }
    }
    
  4. 上面代码,如果正常执行没有问题的,但是如果代码执行过程中出现异常,有问题数据就不正常

    解决方法用事务操作

    • 开启事务
    • 进行业务操作
    • 没有发生异常,提交事务
    • 出现异常,事务回滚

事务操作(Spring 事务管理介绍)

  1. 事务添加到JavaEE三层结构里面Service层(业务逻辑层)

  2. 在Spring进行事务的管理操作

    (1)有两种方式:编程式事务管理和声明式事务管理(使用)

  3. 声明式事务管理

    (1)基于注解方式

    (2)基于xml配置文件方式

  4. 在Spring进行声明式事务管理,底层AOP原理

  5. spring事务管理API

    (1)提供一个接口,代表事务管理器,这个接口针对不同的框架提供不同的实现类

事务操作(注解声明式事务管理)

  1. 在spring:配置文件中配置事务管理器

    <!--创建事务管理器-->
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource"></property>
         </bean>
    
  2. 在spring配置文件,开启事务注解

    (1)在sprng引入名称空间(tx)

    <?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:p="http://www.springframework.org/schema/p"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xsi:schemaLocation=" http://www.springframework.org/schema/beans
                                http://www.springframework.org/schema/beans/spring-beans.xsd
                                http://www.springframework.org/schema/aop
                                http://www.springframework.org/schema/aop/spring-aop.xsd
                                http://www.springframework.org/schema/context
                                http://www.springframework.org/schema/context/spring-context.xsd
                                http://www.springframework.org/schema/tx
                                http://www.springframework.org/schema/tx/spring-tx.xsd
    ">
    

    (2)开启事务的注解

    <!--       开启事务注解-->
            <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
    
    
  3. 在service类声明或者(获取service类里面方法上面)添加事务注解

    (1)@Transactional这个注解可以添加到类上面也可以添加到方法上面,也可以添加方法上面

    (2)如果把这个注解添加类上面,这个类里面所有的方法都添加事务

    (3)如果把这个注解添加到方法上面,为这个方法添加事务

    @Service
    @Transactional
    public class UserService {
    

事务操作(声明式事务管理参数配置)

  1. 在service类上面添加注解@Transactional,在这个注解里面可以配置事务相关系数

  2. 参数propagation 事务传播行为

    (1)多事务方法直接进行调用,这个过程中事务是如何进行管理的

    • 事务方法:对数据库表数据进行变化的操作 (比如增删改)

      @Transactional
      public void add(){
      //调用update方法
      update();
      
      }
      
      public void update(){
      }
      

      有事务的add()调用没有事务的update()

      spring7种传播行为

      事务传播行为类型说明
      PROPAGATION_REQUIRED如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。
      PROPAGATION_SUPPORTS支持当前事务,如果当前没有事务,就以非事务方式执行。
      PROPAGATION_MANDATORY使用当前的事务,如果当前没有事务,就抛出异常。起
      PROPAGATION_REQUIRES_NEW新建事务,如果当前存在事务,把当前事务挂起。
      PROPAGATION_NOT_SUPPORTED以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
      PROPAGATION_NEVER以非事务方式执行,如果当前存在事务,则抛出异常。
      PROPAGATION_NESTED如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作
      • REQUIRED

        如果add方法本身有事务,调用update方法后,update使用当前add方法里面事务

        如果add方法本身没有事务,调用update方法后,创建新事务

      • PROPAGATION_REQUIRES_NEW

        使用add方法调用update方法,如果add无论是否有事务,都创建新的事务

  3. isolation:事务隔离级别

    (1)事务有一个特性成为隔离性,多事务操作直接不会产生影响,不考虑隔离性会产生很多问题

    (2)有三个读问题,脏读,不可重复读,虚(幻)读

    (3)脏读:一个未提交事务读取到另一个未提交的数据

    (4)不可重复读:一个未提交事务读取到另一提交事务中

    (5)虚读:一个未提交事务读取到另一提交事务修改数据

    (6)解决:通过设置事务隔离性,解决读问题

    4

    脏读不可重复读幻读
    READ UNCOMMITTED(读未提交)
    READ COMMITTED(读已提交)
    REPEARABLE READ(可重复读)
    SERIALIZABLE(串行化)
    @Service
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.REPEATABLE_READ)
    public class UserService {
    
  4. timeout:超时时间

    (1)事务需要在一定时间内进行提交 ,如果不提交 进行回滚

    (2)默认时间是-1 这只时间是以秒为单位

    @Service
    @Transactional(timeout = -1,propagation = Propagation.REQUIRED,isolation = Isolation.REPEATABLE_READ)
    public class UserService {
    
  5. readOnly:是否只读

    (1)读:查询操作,写:添加修改删除操作

    (2)readOnly:默认值false,表示可以查询,可以添加修改删除操作

    (3)设置readOnly值是true,设置成true之后,只能查询

    @Service
    @Transactional(readOnly = false,timeout = -1,propagation = Propagation.REQUIRED,isolation = Isolation.REPEATABLE_READ)
    public class UserService {
    
  6. rollbackFor:回滚

    (1)设置查询出现了那些异常进行事务回滚

  7. noRollbackFor:不回滚

    (1)设置出现那些异常不执行事务回滚

事务操作(xml声明式事务管理)

  1. 在spring配置文件中进行配置

    第一步 配置事务管理器

    第二步 配置通知

    第三步 配置切入点和切面

    <?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:p="http://www.springframework.org/schema/p"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xsi:schemaLocation=" http://www.springframework.org/schema/beans
                                http://www.springframework.org/schema/beans/spring-beans.xsd
                                http://www.springframework.org/schema/aop
                                http://www.springframework.org/schema/aop/spring-aop.xsd
                                http://www.springframework.org/schema/context
                                http://www.springframework.org/schema/context/spring-context.xsd
                                http://www.springframework.org/schema/tx
                                http://www.springframework.org/schema/tx/spring-tx.xsd
    ">
    <!--    开启组件的扫描-->
        <context:component-scan base-package="com.atguigu"></context:component-scan>
        
        <!-- 配置连接池 -->
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
              destroy-method="close">
            <property name="url" value="jdbc:mysql:///user_db?useUnicode=true&amp;characterEncoding=utf8" />
            <property name="username" value="root" />
            <property name="password" value="wrm200146" />
            <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        </bean>
        <!--创建事务管理器-->
        <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
            <!--    注入dateSource-->
            <property name="dataSource" ref="dataSource"></property>
        </bean>
    <!--    创建JdbcTemplate对象-->
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <!--注入数据源-->
            <property name="dataSource" ref="dataSource"></property>
         </bean>
    
        <!--2 配置通知-->
        <tx:advice id="txadvice">
            <!--配置事务参数-->
            <tx:attributes>
                <!--指定哪种规则的方法上面添加事务-->
                <tx:method name="accountMoney" propagation="REQUIRED"/>
                <!--<tx:method name="account*"/>-->
            </tx:attributes>
        </tx:advice>
    
    
    <!--    配置切入点和切面-->
        <aop:config>
    <!--        配置切入点-->
            <aop:pointcut id="pt" expression="execution(* com.atguigu.spring5.service.UserService.*(..))"/>
    <!--配置切面-->
            <aop:advisor advice-ref="txadvice" pointcut-ref="pt"/>
        </aop:config>
    
    
    </beans>
    

事务操作(完全注解声明式事务管理)

  1. 创建配置类,使用配置类替代xml配置文件

    package config;
    
    import com.alibaba.druid.pool.DruidDataSource;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.jdbc.core.JdbcTemplate;
    import org.springframework.jdbc.datasource.DataSourceTransactionManager;
    import org.springframework.transaction.annotation.EnableTransactionManagement;
    
    import javax.sql.DataSource;
    
    @Configuration
    @ComponentScan(basePackages = "com.atguigu")//组件扫描
    @EnableTransactionManagement//开启事务
    public class Txconfig {
    
        @Bean
        public DruidDataSource getDruidDataSource(){
            DruidDataSource dataSource=new DruidDataSource();
            dataSource.setDriverClassName("com.alibaba.druid.pool.DruidDataSource");
            dataSource.setUrl("jdbc:mysql:///user_db?useUnicode=true&characterEncoding=utf8");
            dataSource.setUsername("root");
            dataSource.setPassword("wrm200146");
            return dataSource;
    //            <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
    //        destroy-method="close">
    //        <property name="url" value="jdbc:mysql:///user_db?useUnicode=true&amp;characterEncoding=utf8" />
        }
        //创建jdbcTemplate对象
        @Bean
        public JdbcTemplate getJdbcTemplate(DataSource dataSource){
            JdbcTemplate jdbcTemplate=new JdbcTemplate();
                jdbcTemplate.setDataSource(dataSource);
            return jdbcTemplate;
        }
    //    开启事务管理器
        @Bean
        public DataSourceTransactionManager dataSourceTransactionManager(DataSource dataSource){
            DataSourceTransactionManager transactionManager=new DataSourceTransactionManager();
            transactionManager.setDataSource(dataSource);
            return transactionManager;
        }
    }
    
    
    
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

狐狸i

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值