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

MyBatis笔记

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

MyBatis笔记

mybatis 1、简介 1.1、如何获得mybatis
  • maven仓库:

    
    
        org.mybatis
        mybatis
        3.5.9
    
    
  • Github:https://github.com/mybatis/mybatis-3/releases

  • mybatis中文文档:https://mybatis.org/mybatis-3/zh/index.html

1.2、持久化

数据持久化

  • 持久化就是将程序的数据在持久状态和瞬时状态转化的过程

  • 内存:断电即失

  • 数据库(jdbc),io文件持久化。

  • 生活中例子:冷藏,罐头……

为什么需要数据持久化?

- 有一些对象,绝对不能让它丢失
- 内存太贵了,
1.3、持久层

Dao层,Service层,Controler层

  • 完成持久化工作的代码块
  • 层界限十分明显
1.4、为什么需要mybatis?
  • 传统的JDBC代码太复杂了——简化——框架——自动化
  • 帮助程序员将数据存入到数据库中
  • 不用mybatis也可以,当学了之后,更容易上手。技术没有高低之分
  • 优点:

最重要的一点:使用的人多

2、第一个mybatis程序

思路:搭建环境–>导入mybatis–>编写代码–>测试

2.1、搭建环境
  • 搭建数据库
CREATE DATABASE `mybatis`;

USE `mybatis`;

CREATE TABLE `user`(
`id` INT(20) NOT NULL PRIMARY KEY,
`name` VARCHAr(30) DEFAULT NULL,
`pwd` VARCHAr(30) DEFAULT NULL

)ENGINE = INNODB DEFAULT CHARSET = utf8;

INSERT INTO `user`(`id`,`name`,`pwd`)
VALUES (1,'一北','123456'),
(2,'张三','123121'),
(3,'李四','121216') 
  • 新建项目
  1. 新建一个普通的maven项目

  2. 删除src目录,将其当作一个父工程

  3. 导入maven依赖

    
        
    
            
                mysql
                mysql-connector-java
                8.0.28
            
    
            
                org.mybatis
                mybatis
                3.5.9
            
    
            
                junit
                junit
                4.12
            
        
    
2.2、创建一个项目
  • 编写mybatis的核心配置文件

    
    
    
    
    
        
            
                
                
                    
                    
                    
                    
                
            
        
        
            
        
    
    
  • 编写mybatis的工具类

public class MybatisUtils {

    private static SqlSessionFactory sqlSessionFactory;
    static {
        //使用mybatis第一步获取sqlSessionFactory对象
        try {
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static SqlSession getSqlSession(){
       return sqlSessionFactory.openSession();
    }
}
2.3、编写代码
  • 实体类
public class User {
    private int id;
    private String name;
    private String pwd;

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + ''' +
                ", pwd='" + pwd + ''' +
                '}';
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

    public User(int id, String name, String pwd) {
        this.id = id;
        this.name = name;
        this.pwd = pwd;
    }

    public User() {
    }
}
  • Dao接口
public interface UserDao {
    List getUserList();
}
  • 接口实现类 — 由原来的UserDaoImpl改变为Mapper配置文件




    
        select * from mybatis.user
    

2.4、测试
  • junit测试

    public class UserDaoTest {
         @Test
        public void test(){
             //第一步:获得SqlSession的对象
             SqlSession sqlSession = MybatisUtils.getSqlSession();
             //第二步:执行sql
             UserDao mapper = sqlSession.getMapper(UserDao.class);
             List userList = mapper.getUserList();
    
             for (User user : userList) {
                 System.out.println(user);
             }
    
             //关闭sql
             sqlSession.close();
    
    
         }
    }
    

org.apache.ibatis.binding.BindingException: Type interface com.bei.dao.UserDao is not known to the MapperRegistry.

  • MapperRegistry是什么

    在核心配置文件中注册mappers

  • maven导出资源问题

    
        
            
                
                    src/main/resources
                    
                        ***.xml
                    
                    true
                
                
                    src/main/java
                    
                        ***.xml
                    
                    true
                
            
        
    
  • 配置

    driver="com.mysql.cj.jdbc.Driver"
    url="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC"
    name="root"
    password="abc123"
    
3、CRUD
  • id:就是对应namespace 中的方法名
  • resultType:sql语句执行的返回值
  • parameterType:参数类型
  1. 编写接口

    //查询全部用户
    List getUserList();
    
  2. 编写对应的mapper中的sql语句

    
        select * from mybatis.user where id = #{id}
    
    
    • resultMap 元素是 MyBatis 中最重要最强大的元素。
    • ResultMap 的设计思想是,对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了。
    • 在学习了上面的知识后,你会发现上面的例子没有一个需要显式配置 ResultMap,这就是 ResultMap 的优秀之处——你完全可以不用显式地配置它们。
    • 如果这个世界总是这么简单就好了。
    6、日志 6.1、日志工厂

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

    曾经:sout、debug

    现在:日志工厂

    设置名描述有效值默认值
    logImpl指定 MyBatis 所用日志的具体实现,未指定时将自动查找。SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING未设置
    • SLF4J
    • **LOG4J **【掌握】
    • LOG4J2
    • JDK_LOGGING
    • COMMONS_LOGGING
    • **STDOUT_LOGGING ** 【掌握】
    • NO_LOGGING

    在MyBatis中具体使用哪一个日志实现,在设置中设定

    STDOUT_LOGGING标准日志输出

    在MyBatis核心配置文件中,配置我们的日志

    6.2、LOG4J

    什么是Log4j

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

      
      
          log4j
          log4j
          1.2.17
      
      
    2. 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/bei.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][%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. 配置log4j为日志的实现

      
            
      
      
    4. LOG4J的使用 — 直接测试运行刚才的查询

    简单使用

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

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

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

      logger.info("info:进入了testLog4j方法");
      logger.debug("debug:进入了testLog4j方法");
      logger.error("error:进入了testLog4j方法");
      
    7、分页

    思考:为什么需要分页?

    • 减少数据的处理量
    7.1、使用Limit分页

    语法

    select * from user limit startIndex,pageSize;
    select * from user limit 3;  #[0,,n]
    

    使用MyBatis实现分页,核心Sql

    1. 接口

      //分页
      List getUserByLimit(Map map);
      
    2. Mapper.xml

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

      @Test
      public void getUserByLimit(){
          SqlSession sqlSession = MybatisUtils.getSqlSession();
          UserMapper mapper = sqlSession.getMapper(UserMapper.class);
          Map map = new HashMap<>();
          map.put("startIndex",1);
          map.put("pageSize",2);
      
          List userList = mapper.getUserByLimit(map);
          for (User user : userList) {
              System.out.println(user);
          }
          sqlSession.close();
      }
      
    7.2、RowBounds分页

    不再使用sql实现分页

    1. 接口

      //分页2
      List getUserByRowBounds();
      
    2. Mapper.xml

      
              select *
              from teacher where id=#{tid};
          
      
      1. 按照结果嵌套处理
      
      
          select s.id sid,s.name sname,t.id tid,t.name tname
          from teacher t,student s
          where s.tid = t.id and t.id = #{tid};
      
      
          
          
          
          
              
              
              
          
      
      

      按照查询嵌套处理

      
          select *
          from student
          where tid=#{tid};
      
      

      小结:

      1. 关联(association)【多对一】

      2. 集合(collection)【一对多】

      3. javaType & ofType

        • javaType 用来指定实体类中属性的类型
        • ofType用来指定映射到list或者集合中的pojo类型,泛型中的约束类型

      注意点:

      • 保证sql的可读性,尽量保证通俗易懂
      • 注意一对多和多对一,里面的属性名和字段的问题
      • 如果问题不好排查错误,可以使用日志,建议使用log4j

      面试高频:

      • MySQL引擎
      • innodb底层原理
      • 索引
      • 索引优化
      12、动态sql

      什么是动态sql:动态sql就是根据不同的条件生成不同的sql语句

      如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。

      • if
      • choose (when, otherwise)
      • trim (where, set)
      • foreach

      搭建环境

      CREATE TABLE `blog`(
      `id` varchar(50) NOT NULL COMMENT '博客id',
      `title` varchar(100)  NOT NULL COMMENT '博客标题',   
      `author` varchar(30)  NOT NULL COMMENT '博客作者', 
      `create_time` datetime  NOT NULL COMMENT '创建时间',
      `views` int(30)  NOT NULL COMMENT '浏览量'
      )ENGINE=InnoDB DEFAULT CHARSET=utf8
      

      创建一个基础工程

      1. 导包

      2. 编写配置文件

      3. 编写实体类

        @Data
        public class Blog {
            private int id;
            private String title;
            private String author;
            private Date createTime;
            private int views;
        }
        
      4. 编写实体类对应的Mapper接口和Mapper.xml文件

      IF

      
          select *
          from blog
          
              
                  
                      title like #{title}
                  
                  
                      and author like %#{author}%
                  
                  
                      and views =#{views}
                  
              
          
      
      

      trim、where、set

      
          select *
          from blog
          
              
          
      
      

    注意事项:

    • 最好基于单表来定义sql片段
    • 不要存在where标签
    • 尽量只包含if标签

    动态sql就是在拼接sql语句,我们只要保证sql的正确性,按照sql的格式,去排列组合就好了

    建议:

    • 先在MySQL中写出完整的sql,再对应去修改成我们的动态sql,实现通用
    13、缓存 13.1、简介
    查询   :  连接数据库    ,   耗资源
    一次查询的结果,给他暂存到一个可以直接取到的地方  =》内存;即缓存
    我们再次查询相同数据的时候,直接去缓存中拿,就不用走数据库了
    

    读写分离、主从复制

    1. 什么是缓存【cache】?
      • 存在内存中的临时数据
      • 将用户经常查询的数据放在缓存(内存)中,用户去查询就不用从磁盘上(关系型数据库数据文件)查询,从缓存中查询,从而提高查询效率,解决高并发系统的性能问题
    2. 为什么使用缓存?
      • 减少和数据库的交互次数,减少系统开销,提高系统效率
    3. 什么样的数据该使用缓存?
      • 经常查询且不经常改变的数据
    13.2、MyBatis缓存
    • MyBatis包含一个非常强大的查询缓存特性,它可以非常方便地定制和配置缓存。缓存可以极大的提升查询效率。
    • MyBatis系统中默认定义了两级缓存:一级缓存和二级缓存
      • 默认情况下,只有一级缓存开启。(SqlSession级别的缓存,也称本地缓存)
      • 二级缓存需要手动开启和配置,它是基于namespace级别的缓存
      • 为了提高扩展性,MyBatis定义了缓存接口Cache。我们可以通过实现Cache接口来自定义二级缓存
    13.3、一级缓存
    • 一级缓存也叫本地缓存
      • 与数据库同一次会话期间查询到的数据会放在本地缓存中;
      • 以后如果需要获取相同的数据,直接从缓存中拿,没必要再去查询数据库。

    测试步骤:

    1. 开启日志

    2. 测试在一个session中查询两次相同的记录

    3. 查看日志输出

    缓存失效的情况:

    1. 查询不同数据

    2. 增删改,可能会改变原来的数据,所以必定会刷新缓存

    3. 查询不同的Mapper.xml

    4. 手动清理缓存

      @Test
      public void test(){
          SqlSession sqlSession = MybatisUtils.getSqlSession();
      
          List users = sqlSession.getMapper(UserMapper.class).queryUserById(1);
          for (User user : users) {
              System.out.println(user);
          }
          
          System.out.println("******************************************");
          sqlSession.clearCache();//手动清理缓存
          List users2 = sqlSession.getMapper(UserMapper.class).queryUserById(1);
          for (User user : users2) {
              System.out.println(user);
          }
          System.out.println(users==users2);
          sqlSession.close();
      }
      

    小结:

    • 一级缓存默认是开启的,只在一次Sqlsession中有效,也就是拿到连接到关闭连接这个时间段

    • 一级缓存就是一个map

    13.4、二级缓存
    • 二级缓存也叫全局缓存,一级缓存作用域太低了,故诞生了二级缓存;
    • 基于namespace级别的缓存,一个命名空间对应一个二级缓存;
    • 工作机制:
      • 一个会话查询一条数据,这个数据就会被放在当前会话的一级缓存中;
      • 如果当前会话关闭了,这个会话对应的一级缓存就没了;但是我们想要的是,会话关闭了,一级缓存中的数据被保存到二级缓存中;
      • 新的会话查询信息,就可以从二级缓存中获取内容;
      • 不同的Mapper查出的数据会放在自己对应的缓存(map)中。

    步骤:

    1. 开启全局缓存

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

      
      
      

      也可以自定义参数

      
      
      
    3. 测试

      1. 我们需要将实体类序列化,否则就会报错

        Caused by: java.io.NotSerializableException: com.bei.pojo.User

    4. 小结:

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

    缓存顺序:

    1. 先看二级缓存中有无
    2. 再看一级缓存中有无
    3. 最后无可奈何才查询数据库

    13.6、自定义缓存-ehcache 现已多用redis代替

    ehcache 是一种广泛使用的开源Java分布式缓存,主要面向通用缓存

    要在程序中使用ehcache,先要导包

    
    
        org.mybatis.caches
        mybatis-ehcache
        1.2.2
    
    

    在mapper中指定使用我们的ehcache缓存实现

    
    
    

    ehcache.xml

    
    
        
        
        
    
        
    
        
        
    
    
    

    Redis数据库来做缓存

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

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

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