栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Mybatis学习笔记

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Mybatis学习笔记

Mybatis学习笔记

本篇文章是观看B站UP主狂神说关于Mybatis讲解的视频,借鉴Mybatis官方文档以及CSDN博主黑心白莲相关文章整理的个人Mybatis笔记。因笔者能力有限,文章难免有错误之处,欢迎各位评论勘误,共同探讨!

文章目录
  • Mybatis学习笔记
    • 1、Mybatis简介
      • 1.1 什么是Mybatis
      • 1.2 数据持久化
      • 1.3 持久层
      • 1.4 为什么需要使用Mybatis
    • 2、第一个Mybatis程序
      • 2.1 搭建环境
      • 2.2 创建 Module
      • 2.3 编写代码
    • 3、基本CRUD操作
      • 3.1 命名空间 Namespace
      • 3.2 查询—select
      • 3.3 添加—insert
      • 3.4 更新—update
      • 3.5 删除—delete
      • 3.6 注意点
      • 3.7 模糊查询
      • 3.8 万能 Map
    • 4、Mybatis配置解析
      • 4.1 核心配置文件
      • 4.2 环境配置
      • 4.3 属性 properties
      • 4.4 类型别名 typeAliases
      • 4.5 设置 Settings
      • 4.6 其他配置
      • 4.7 映射器 mappers
      • 4.8 作用域和生命周期
    • 5、日志
      • 5.1 日志工厂
      • 5.2 LOG4J
    • 6、分页
      • 6.1 为什么要分页?
      • 6.2 使用 Limit 分页
      • 6.3 RowBounds 分页
      • 6.4 [分页插件](https://pagehelper.github.io/)
    • 7、动态SQL
      • 7.1 搭建环境
      • 7.2 if
      • 7.3 choose(when, otherwise)
      • 7.4 trim(where, set)
    • 8、缓存
      • 8.1 简介
        • 1. 什么是缓存 (Cache)?
        • 2. 为什么使用缓存?
        • **3. **什么样的数据能使用缓存**?**
      • 8.2 Mybatis 缓存
      • 8.3 一级缓存
        • 8.3.1 测试步骤
        • 8.3.2 缓存失效的情况
      • 8.4 二级缓存
        • 8.4.1 使用步骤
      • 8.5 缓存原理
    • 9、可能遇到的问题
      • 9.1 属性名和字段名不一致的问题
      • 9.2 资源导出失败的问题
      • 9.2 资源导出失败的问题

1、Mybatis简介 1.1 什么是Mybatis

  • MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。

  • MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。

  • MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

  • Maven仓库

    
        org.mybatis
        mybatis
        3.5.7
    
    
  • 中文文档:链接

  • GitHub:链接

1.2 数据持久化
  • 持久化:将程序的数据从瞬时状态转化为持久状态的过程
  • 原因:内存断电即失,内存条价格较昂贵
  • 实现方式:I/O文件操作、数据库存储(JDBC技术)
1.3 持久层
  • 完成持久化工作的代码块
  • 层可以使实现不同功能代码的界限明显
  • Dao层/Mapper层
1.4 为什么需要使用Mybatis
  • 传统的JDBC代码过于复杂
  • 半自动化的框架可以帮助程序员更方便地将数据存入数据库
  • 不使用Mybatis也可以,技术没有高低之分
2、第一个Mybatis程序 2.1 搭建环境

搭建数据库

新建项目

  1. 创建一个普通的 Maven 项目

  2. 删除 src 目录(可将此项目作为父项目,然后创建子项目)

  3. 在 pom.xml 文件中导入 Maven 依赖

        
            
            
                mysql
                mysql-connector-java
                8.0.25
            
            
            
                org.mybatis
                mybatis
                3.5.6
            
            
            
                junit
                junit
                4.12
                test
            
        
    
  4. 右键项目名创建一个模块 Module

2.2 创建 Module
  • 编写 Mybatis 的核心配置文件(mybatis-config.xml)

    
    
    
    
        
            
                
                
                    
                    
                    
                    
                
            
        
    
    
  • 编写 Mybatis 工具类文件(MybatisUtils.java)

    public class MybatisUtils {
        private static SqlSessionFactory sqlSessionFactory;
    
        //使用Mybatis获取SqlSessionFactory对象
        static {
            InputStream inputStream = null;
            try {
                String resource = "mybatis-config.xml";
                inputStream = Resources.getResourceAsStream(resource);
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        
        public static SqlSession getSqlSession() {
            return sqlSessionFactory.openSession();
        }
    }
    
2.3 编写代码
  • 实体类 pojo / Bean

  • Dao 接口 (UserMapper.java)

    public interface UserMapper {
        
        User getUserById(int id);
    }
    
  • 接口实现文件(UserMapper.xml)

    
    
    
    
        
            select * from mybatis.user
    
    
    • id:对应的 namespace 中的方法名
    • resultType:sql语句执行的返回值类型
    • parameterType:参数类型
  • 测试

    @Test
    public void getUserList() {
        //1.获取sqlSession
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        //2.执行sql语句
        try{
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            List userList = userMapper.getUserList();
            for (User user : userList) {
                System.out.println(user);
            }
        } finally {
            //3.关闭sqlSession
            sqlSession.close();
        }
    }
    
  • 3.3 添加—insert
    1. 接口中添加方法

      int addUser(User user);
      
    2. 在对应的 Mapper.xml 文件中编写SQL语句

      
          insert into mybatis.user(id, name, pwd) VALUES (#{id}, #{name}, #{pwd})
      
      
    3. 测试

      @Test
      public void addUser() {
          SqlSession sqlSession = MybatisUtils.getSqlSession();
          UserMapper mapper = sqlSession.getMapper(UserMapper.class);
          int res = mapper.addUser(new User(4, "小王", "666666"));
          if (res > 0) System.out.println("用户添加成功! ");
          //增删改必须提交事务
          sqlSession.commit();
          sqlSession.close();
      }
      
    3.4 更新—update
    1. 接口中添加方法

      int updateUserById(User user);
      
    2. 在对应的 Mapper.xml 文件中编写SQL语句

      
          update mybatis.user set name = #{name}, pwd = #{pwd} where id = #{id}
      
      
    3. 测试

      @Test
      public void updateUserById() {
          SqlSession sqlSession = MybatisUtils.getSqlSession();
          UserMapper mapper = sqlSession.getMapper(UserMapper.class);
          int res = mapper.updateUserById(new User(5, "小杨", "987654"));
          if(res > 0) {
              System.out.println("用户修改成功! ");
          }
          //增删改必须提交事务
          sqlSession.commit();
          sqlSession.close();
      }
      
    3.5 删除—delete
    1. 接口中添加方法

      int deleteUserById(int id);
      
    2. 在对应的 Mapper.xml 文件中编写SQL语句

      
          delete from mybatis.user where id = #{id}
      
      
    3. 测试

      @Test
      public void deleteUserById() {
          SqlSession sqlSession = MybatisUtils.getSqlSession();
          UserMapper mapper = sqlSession.getMapper(UserMapper.class);
          int res = mapper.deleteUserById(4);
          if(res > 0) {
              System.out.println("用户删除成功! ");
          }
          //增删改都需要提交事务
          sqlSession.commit();
          sqlSession.close();
      }
      
    3.6 注意点

    增删改操作一定要提交事务!!!

    sqlSession.commit();
    
    3.7 模糊查询
    1. 在Java代码执行的时候,传递通配符% %

      List userList = mapper.getUserLike("%王%");
      
    2. 在sql拼接中使用通配符

      select * from user where name like "%"#{value}"%"
      
    3.8 万能 Map

    当实体类的属性或数据库中的字段过多时,应当考虑使用Map.

    1. UserMapper.java

      //用万能 Map 插入用户
      public void addUser2(Map map);
      
    2. UserMapper.xml

      
          insert into user (id,name,password) values (#{userid},#{username},#{userpassword})
      
      
    3. 测试

      @Test
      public void addUser2(){
          SqlSession sqlSession = MybatisUtils.getSqlSession();
          UserMapper mapper = sqlSession.getMapper(UserMapper.class);
          HashMap map = new HashMap();
          map.put("userid",4);
          map.put("username","小王");
          map.put("userpassword","789789");
          mapper.addUser2(map);
          //提交事务
          sqlSession.commit();
          //关闭资源
          sqlSession.close();
      }
      
    4、Mybatis配置解析 4.1 核心配置文件
    • mybatis-config.xml

    • Mybatis的配置文件包含了Mybatis行为的设置和属性信息。

      configuration(配置)
          properties(属性)
          settings(设置)
          typeAliases(类型别名)
          typeHandlers(类型处理器)
          objectFactory(对象工厂)
          plugins(插件)
          environments(环境配置)
          	environment(环境变量)
          		transactionManager(事务管理器)
          		dataSource(数据源)
          databaseIdProvider(数据库厂商标识)
          mappers(映射器)
      
    4.2 环境配置
    • Mybatis 可以配置多个环境,但是每个 SqlSessionFactory 实例只能选择一种环境。
    • Mybatis 默认的事务管理器是 JDBC,连接池:POOLED
    4.3 属性 properties
    • 可以通过 properties 属性来实现引用配置文件;
    • 属性可以在外部进行配置,并且可以进行动态替换(例如:典型的 Java属性文件【db.properties】);
    • 属性也可以在 properties 元素的子元素中设置。
    1. 编写一个配置文件 db.properties

      driver=com.mysql.cj.jdbc.Driver
      url=jdbc:mysql://localhost:3306/数据库名?userSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
      username=用户名
      password=密码
      
    2. 在核心配置文件中引入

      
          
          
      
      

      注意点:如果外部文件(例如:db.properties)和核心配置文件(mybatis-config.xml)有相同字段,则优先使用外部配置文件中的属性值。

    4.4 类型别名 typeAliases
    • 可以为 Java 类型设置一个缩写名字,仅用于 XML 配置;
    • 目的是降低冗余的全限定类名书写。
    
        
    
    

    也可以指定一个包,每一个在包 com.sit.pojo 中的 Java Bean, 在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。例如 com.sit.pojo.User 的别名为 user ; 若有注解,则别名为其注解值。

    
        
    
    
    • 在实体类比较少的时候,使用第一种方式(可以自定义别名);
    • 如果实体类很多,则使用第二种扫描包的方式。
    4.5 设置 Settings
    • Mybatis 中极为重要的调整设置,会改变 Mybatis 的运行时行为。
    
            
    
        	
        	
            
            
        	
            
    
    
    4.6 其他配置
    • typeHandlers(类型处理器)
    • objectFactory(对象工厂)
    • plugins (插件)
      • mybatis-generator-core
      • mybatis-plus
      • 通用mapper
    4.7 映射器 mappers

    MapperRegistry:注册绑定 Mapper 文件;

    方式一:使用 xml 文件绑定注册【推荐使用】

    
        
    
    

    方式二:使用 class 文件绑定注册

    
        
    
    

    注意点:

    • 接口和它的Mapper配置文件必须同名
    • 接口和它的Mapper配置文件必须在同一个包下

    方式三:使用包扫描进行注入

    
        
    
    
    4.8 作用域和生命周期


    作用域和生命周期是至关重要的,错误地使用会导致严重的并发问题。

    SqlSessionFactoryBuilder:

    • 一旦创建了 SqlSessionFactory,就不再需要它了
    • 属于局部变量

    SqlSessionFactory:

    • 可以想象为:数据库连接池
    • SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例;
    • SqlSessionFactory 的最佳作用域是应用作用域;
    • 最简单的就是使用单例模式或静态单例模式。

    SqlSession:

    • 可以想象为:连接到连接池的一个请求
    • SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳作用域是请求或方法作用域;
    • 用完需要及时关闭,否则会一直占用资源!

    图示中每一个 Mapper 代表一个具体的业务!

    5、日志 5.1 日志工厂

    如果一个数据库操作出现了异常,日志是排错的最好助手!

    曾经:sout、debug

    现在:日志工厂

    • SLF4J
    • LOG4J 【掌握】
    • LOG4J2
    • JDK_LOGGING
    • COMMONS_LOGGING
    • STDOUT_LOGGING【掌握】
    • NO_LOGGING

    在 mybatis-config.xml 的 Settings 中设置具体使用的日志

    STDOUT_LOGGING 标准日志工厂的实现

    
            
    	    
    
    

    5.2 LOG4J

    什么是 Log4j ?

    • Log4j 是 Apache 的一个开源项目,通过使用 Log4j,可以控制日志信息输送的目的地是控制台、文件、GUI组件;
    • 也可以控制每一条日志的输出格式;
    • 通过定义每一条日志信息的级别,能够更加细致地控制日志的生成过程;
    • 可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。
    1. 先在 pop.xml 文件中导入 LOG4J 的依赖包

      
      		
              
                  log4j
                  log4j
                  1.2.17
              
          
      
    2. 在 resources 文件夹下建立 log4j.properties 文件进行配置

      #将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
      log4j.rootLogger=DEBUG,console,file
      
      #控制台输出的相关设置
      log4j.appender.console = org.apache.log4j.ConsoleAppender
      log4j.appender.console.Target = System.out
      log4j.appender.console.Threshold=DEBUG
      log4j.appender.console.layout = org.apache.log4j.PatternLayout
      log4j.appender.console.layout.ConversionPattern=[%c]-%m%n
      
      #文件输出的相关设置
      log4j.appender.file = org.apache.log4j.RollingFileAppender
      log4j.appender.file.File=./log/log4j.log
      log4j.appender.file.MaxFileSize=10mb
      log4j.appender.file.Threshold=DEBUG
      log4j.appender.file.layout=org.apache.log4j.PatternLayout
      log4j.appender.file.layout.ConversionPattern=[%p][20%d{yy-MM-dd}][%c]%m%n
      
      #日志输出级别
      log4j.logger.org.mybatis=DEBUG
      log4j.logger.java.sql=DEBUG
      log4j.logger.java.sql.Statement=DEBUG
      log4j.logger.java.sql.ResultSet=DEBUG
      log4j.logger.java.sql.PreparedStatement=DEBUG
      
    3. 在 mybatis-config.xml 核心配置文件中配置 Log4j 为日志工厂的实现

      
              
              
      
      
    4. Log4j 的测试运行

    简单使用

    1. 在要使用 Log4j 的测试类中,导入包 org.apache.log4j.Logger

    2. 日志对象,参数为当前类的class

      static Logger logger = Logger.getLogger(UserMapperTest.class);
      
    3. 日志级别

      logger.info("info: 进入了testLog4j");
      logger.debug("debug: 进入了testLog4j");
      logger.error("erro: 进入了testLog4j");
      
    4. 之后可在 log 文件夹中查看日志文件信息

    6、分页 6.1 为什么要分页?
    • 减少数据的处理量
    6.2 使用 Limit 分页
    语法:SELECt * from tableName limit startIndex,pageSize
    例如:SELECt  * from user limit 3 #[0,n-1]
    
    1. 接口

      List getUsersByLimit(Map map);
      
    2. Mapper.xml

      
      	select * from mybatis.user limit #{startIndex},#{pageSize}
      
      
    3. 测试

      @Test
      public void getUsersByLimit(){
          SqlSession sqlSession = MybatisUtils.getSqlSession();
          UserMapper mapper = sqlSession.getMapper(UserMapper.class);
      
          HashMap map = new HashMap();
          map.put("startIndex",0);
          map.put("pageSize",2);
      
          List userList = mapper.getUsersByLimit(map);
          for (User user : userList) {
              System.out.println(user);
          }
      
          sqlSession.close();
      }
      
    6.3 RowBounds 分页
    1. 接口

      List getUsersByRowBounds();
      
    2. Mapper.xml

      
          select * from mybatis.blog where 1=1
          
              and title = #{title}
          
          
              and author = #{author}
          
      
      
      7.3 choose(when, otherwise)
      
          select * from mybatis.blog
          
              
                  and title = #{title}
              
              
                  and author = #{author}
              
          
      
      
      
          update mybatis.blog
          
              title=#{title},
              author=#{author},
          
          where views=#{views}
      
      
      8、缓存 8.1 简介 1. 什么是缓存 (Cache)?
      • 存在内存中的临时数据;
      • 将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用从磁盘上(关系型数据库查询文件)查询,转而从缓存中查询,从而提高了查询效率,解决了高并发系统的性能问题。
      2. 为什么使用缓存?
      • 减少和数据库的交互次数,减少系统开销,提高系统效率。
      3. 什么样的数据能使用缓存?
      • 经常查询并且不经常改变的数据。
      8.2 Mybatis 缓存
      • Mybatis包含一个非常强大的查询缓存特性,它可以非常方便地定制和配置缓存。缓存可以极大的提升查询效率。
      • Mybatis系统中默认定义了两级缓存:一级缓存和二级缓存
        • 默认情况下,只有一级缓存开启。(SqlSession 级别的缓存,也称为本地缓存)
        • 二级缓存需要手动开启和配置,它是基于 namespace 级别的缓存。
        • 为了提高扩展性,Mybatis定义了缓存接口Cache,我们可以通过实现Cache接口来自定义二级缓存。
      8.3 一级缓存
      • 与数据库同一次会话期间查询到的数据会放在本地缓存中;
      • 以后如果需要获取相同的数据,直接从缓存中拿,没必要再去查询数据库。
      8.3.1 测试步骤
      1. 开启日志

      2. 在一个 SqlSession 中查询两次相同的记录

        @Test
        public void testCacheLevel1() {
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            User user = mapper.getUserById(1);
            System.out.println(user);
            System.out.println("===================================");
            User user2 = mapper.getUserById(1);
            System.out.println(user2);
            System.out.println("===================================");
            System.out.println(user == user2);
            System.out.println("===================================");
            sqlSession.close();
        }
        
      3. 查看日志输出

      8.3.2 缓存失效的情况
      1. 查询不同的数据

      2. 执行了增删改操作(由于会改变原有数据,所以必定会刷新缓存!)

      3. 查询不同的 Mapper.xml

      4. 手动清理缓存

        @Test
        public void testCacheLevel1() {
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            
            User user = mapper.getUserById(1);
            System.out.println(user);
            System.out.println("===================================");
            
            //手动清理缓存
            sqlSession.clearCache();
            
            User user2 = mapper.getUserById(1);
            System.out.println(user2);
            System.out.println("===================================");
            
            System.out.println(user == user2);
            System.out.println("===================================");
            sqlSession.close();
        }
        

        测试结果

      小结:

      ​ 一级缓存默认是开启的,只在一次 SqlSession 中有效,也就是拿到连接到关闭连接这个阶段,一级缓存相当于一个 Map。

      8.4 二级缓存
      • 二级缓存也叫全局缓存,是基于 namespace 级别的缓存
      • 工作机制
        • 一个会话查询一条数据,数据会被放在当前会话的一级缓存中;
        • 若当前会话关闭,对应的一级缓存就会消失,此时一级缓存中的数据会被保存到二级缓存中;
        • 新的会话查询信息就可以从二级缓存中获取内容;
        • 不同的 mapper.xml 查出的数据就会放在自己对应的缓存(map)中。
      8.4.1 使用步骤
      1. 在 mybatis-config.xml 开启全局缓存

        
            
            
        
        
      2. 在要使用二级缓存的 mapper.xml 中开启

        
        

        也可以自定义参数

        
        
      3. 测试

        如果没有自定义参数则会报错,需要将实体类序列化!

        Cause: java.io.NotSerializableException: com.sit.pojo.User
        

        解决方案

        public class User implements Serializable {...}
        

      小结:

      • 所有的数据都会先放在一级缓存中;
      • 只要开启了二级缓存,在同一个 mapper.xml 下就有效;
      • 只有当会话提交或者关闭的时候,数据才会提交到二级缓存中。
      8.5 缓存原理

      9、可能遇到的问题 9.1 属性名和字段名不一致的问题

      数据库中的字段

      新建项目中 POJO 的实体类属性

      public class User {
          private int id;
          private String name;
          private String password;
      }
      

      测试出现的问题

      解决方法

      1. 起别名

        
                select * from mybatis.user where id = #{id}
            
        
      9.2 资源导出失败的问题

      在 pop.xml 的 build 中配置 resources

      
      	
      		
                 	src/main/resources
                  
                     	***.xml
                  
                  false
              
              
                  src/main/java
                  
                      ***.xml
                  
                  false
              
          
      
      
      1. 结果集映射(ResultMap)

            
                
                 
                 
                
            
        
            
        
      9.2 资源导出失败的问题

      在 pop.xml 的 build 中配置 resources

      
      	
      		
                 	src/main/resources
                  
                     	***.xml
                  
                  false
              
              
                  src/main/java
                  
                      ***.xml
                  
                  false
              
          
      
      
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/292053.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号