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

Mybatis全笔记

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

Mybatis全笔记

一、MyBatis简介 1.MyBatis历史

MyBatis最初是Apache的一个开源项目iBatis,2010年6月这个项目由Apache迁移到了Google。随着开发团队转投到了Google旗下,iBatis3.X正式更名为MyBatis。(jar包中还有iBatis的身影)

iBatis一词来源于“Internet”和“abatis”的组合,是一个基于Java的持久层框架。

2.MyBatis特性
  1. MyBatis是支持定制化SQL、存储过程以及高级映射的优秀的持久层框架。
  2. MyBatis避免了几乎所有JDBC代码和手动设置参数以及获取结果集。
  3. MyBatis可以使用简单的XML或者注解用于配置和原始映射,将接口和Java的pojo映射成数据库中的记录。
  4. MyBatis是一个半自动的ORM(Object Relation Mapping)框架。
3.MyBatis和Hibernate

Hibernate也是一个持久化框架,但是在国内并没有MyBatis来得火爆。

简单比较两者:

Hibernate比较复杂,庞大,学习周期比较长,开发难度大于MyBatis,很难上手。但是Hibernate有良好的映射机制,能够自动生成sql。但是映射太多,导致数据库性能下降。

MyBatis则相对简单,对JDBC进行了封装,屏蔽了jdbc的缺点,让程序员只需要关注sql本身,容易上手。但是需要手动编写sql。

但是Hibernate自动生成的sql比较复杂,而且对sql语句的优化、修改比较困难,系统不喜欢。MyBatis需要人手动书写sql语句,更灵活,性能更好。

二、快速入门 1.开发环境

IDE:idea 2020.3

构建工具:Maven 3.8.4

MySQL版本:MySQL 8.0.26

2.创建maven工程 a>打包方式
org.example
MyBatis
1.0-SNAPSHOT

jar
b>引入依赖


    mysql
    mysql-connector-java
    8.0.26



    org.mybatis
    mybatis
    3.5.9



    junit
    junit
    4.12
    test



    org.projectlombok
    lombok
    1.18.24
    provided

3.MyBatis的核心配置文件

核心配置文件主要用于配置连接数据库的环境以及MyBatis的全局配置信息。

习惯上命名为 mybatis-config.xml ,这个文件名仅仅是建议,并非强制要求。

在 resources 目录下新建文件 mybatis-config.xml ,粘贴以下信息并填写数据源:




    
    
        
            
            
            
            
                
                
                
                
            
        
    
    
    
        
    

4.数据表和对应实体类 a>tbl_user表
create table tbl_user(
    id int primary key auto_increment,
    username varchar(20),
    password varchar(20),
    age int(11),
    sex char(1),
    email varchar(20)
);
b>User实体类
package com.example.mybatis.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

// getter、setter、toString、hashcode...
@Data
// 全参构造
@AllArgsConstructor
// 无参构造
@NoArgsConstructor
public class User {
    private Integer id;
    private String username;
    private String password;
    private Integer age;
    private String sex;
    private String email;
}
5.创建Mapper接口

MyBatis中的Mapper接口相当于以前的dao。但是区别在于,Mapper仅仅是接口,我们不需要提供实现类。

一张表对应一个Mapper和一个Mapper映射文件。

package com.example.mybatis.mapper;

public interface UserMapper {
    
    int insertUser();
    
}
6.创建MyBatis的映射文件

MyBatis面向接口编程的两个一致:

  1. 映射文件的namespace要和mapper接口的全类名保持一致
  2. 映射文件中SQL语句的id要和mapper接口中的方法名一致

在 resource 下新建目录 mappers ,Mapper映射文件就全部放在里面。





	
    
        insert into tbl_user(username,password,age,sex,email) values('admin','123456',23,'男','12345@qq.com')
    


还需要修改核心配置文件中,映射文件的位置:



    

此时的目录结构:

7.通过junit测试功能

SqlSession:代表Java程序和数据库之间的对话。

SqlSessionFactory:是“生成SqlSession的工厂”

工厂模式:如果创建某一个对象,使用的过程基本固定,那么我们就可以把创建这个对象的相关代码封装到一个“工厂类”中,以后都使用这个工厂类来生产我们需要的对象。

在 test 下新建目录 com.example.mybatis.test,创建 MyBatisTest.java

package com.example.mybatis.test;

import com.example.mybatis.mapper.UserMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;

public class MyBatisTest {

    @Test
    public void testMyBatis() throws IOException {
        // 加载静态方法
        InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
        // 获取SqlSessionFactoryBuilder
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        // 获取SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
        // 获取sqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();

        // 获取mapper接口对象
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

        int user = userMapper.insertUser();
        System.out.println(user);

        // 执行后需要提交事务。jdbc中的executeQuery等执行命令自动会commit。
        sqlSession.commit();
    }
}

  • SqlSession:代表Java程序和数据库之间的会话。
  • SqlSessionFactory:是“生产”SqlSession的工厂。
  • 工厂模式:如果创建某一个对象,使用的过程基本固定,那么我们就可以把创建这个对象的相关代码封装到一个“工厂类”中,以后都使用这个工厂类来“生产”我们需要的对象!
三、优化功能 自动提交事务

由于SqlSession默认不自动提交事务,每次执行完DML语句后,需要手动提交事务。

可以设置为自动提交事务。

SqlSession sqlSession = sqlSessionFactory.openSession(true);
log4j记录日志

在 resource 目录下创建文件 log4j.properties

### 配置根 ###
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.FileAppender
log4j.appender.file.File = logs/lu.log
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=dubug
log4j.logger.java.sql=dubug
log4j.logger.java.sql.Statement=dubug
log4j.logger.java.sql.PreparedStatement=dubug
log4j.logger.java.sql.ResultSet=dubug

日志的级别?

FATAL(致命)->ERROR(警告)->INFO(信息)->DEBUG(调试)

从左到右打印的内容越来越详细。

配置完log4j.properties之后,执行程序之后能够显示mybatis的具体情况和sql语句:

四、测试删改功能 删除
  1. 首先在mapper中写一个删除用户的接口。
public interface UserMapper {
    
    int deleteUser();
}
  1. 在接口对应映射文件中书写该接口执行的sql语句。


	
    
        delete from tbl_user where id = 13;
    

  1. 编写测试方法
@Test
public void testDelete() throws IOException {
    // 加载核心配置文件
    InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
    // 获取SqlSessionFactoryBuilder
    SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
    // 获取SqlSessionFactory
    SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
    // 获取SqlSession,并设置自动commit;
    SqlSession sqlSession = sqlSessionFactory.openSession(true);

    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    
    // 调用删除用户的接口
    int deleteUser = userMapper.deleteUser();
    System.out.println(deleteUser);

}
更新
  1. 首先在mapper中写一个更新用户信息的接口。
public interface UserMapper {
    
    int updateUser();
}
  1. 在接口对应映射文件中书写该接口执行的sql语句。


	
    
        update tbl_user set username = '法外狂徒' where id = 3;
    

  1. 编写测试方法
@Test
public void testUpdate() throws IOException {
    // 加载核心配置文件
    InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
    // 获取SqlSessionFactoryBuilder
    SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
    // 获取SqlSessionFactory
    SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
    // 获取SqlSession,并设置自动commit;
    SqlSession sqlSession = sqlSessionFactory.openSession(true);

    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    
    // 调用更新用户信息的接口
    int updateUser = userMapper.updateUser();
    System.out.println(updateUser);

}
五、测试查询功能 查询单条
  1. 首先在mapper中写一个查询用户的接口。
public interface UserMapper {
    
    User getUserById();
}
  1. 在接口对应映射文件中书写该接口执行的sql语句。


	
    
        select id,username,password,age,sex,email from tbl_user where id = 3;
    

  1. 再次执行程序

查询多条
  1. 首先在mapper中写一个查询所有用户的接口。
public interface UserMapper {
    
    List getAllUser();
}
  1. 在接口对应映射文件中书写该接口执行的sql语句。


	
    
    select id,username,password,age,sex,email from tbl_user;

  • 测试,成功查询到所有数据。

  • 注意:

    类型别名不区分大小写。也就是说 resultType的值写成小写的 user,也可以。

    
        select id, username, password, age, sex, email from tbl_user where username = #{username};
    
    
    1. 测试
    @Test
    public void getUserByUsernameTest(){
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        ParameterMapper sqlSessionMapper = sqlSession.getMapper(ParameterMapper.class);
        User user = sqlSessionMapper.getUserByUsername("法外狂徒");
        System.out.println(user);
    }
    
    1. 结果

    测试2 使用${}
    1. 创建一个mapper接口
    public interface ParameterMapper {
        
        User getUserByUsername(String username);
    }
    
    1. 编写mapper接口对应的方法
    
        select id, username, password, age, sex, email from tbl_user where username = '${username}';
    
    

    总结:

    当mapper接口方法的参数为单个的字面量类型,可以通过KaTeX parse error: Expected 'EOF', got '#' at position 4: {}和#̲{}以任意的名称获取参数值,但…{}的单引号问题。

    mapper接口参数为多个 Mybatis帮忙存储参数
    1. 创建一个mapper接口
    public interface ParameterMapper {
        
        User checkUserLogin(String username, String password);
    }
    
    1. 编写mapper接口对应的方法
    
        
        select * from tbl_user where username = #{arg0} and password = #{arg1};
    
    

    
        select * from tbl_user where username = #{arg0} and password = #{param2};
    
    

    由三组数据可得:

    arg0:第一个参数,arg1:第二个参数;param1:第一个参数,param2:第二个参数

    而且:arg0 = param1 ,arg1 = param2

    当mapper接口方法的参数为多个时,Mybatis会将这些参数放在一个map集合中,以两种方式存储

    a>以 arg0,arg1,… 以键,以参数为值

    b>以 param1,param2,… 以键,以参数为值

    手动用map传入参数
    1. 创建一个mapper接口
    public interface ParameterMapper {
        
        User checkUserLoginByMap(Map map);
    }
    
    1. 编写mapper接口对应的方法
    
        select * from tbl_user where username = #{username} and password = #{password}
    
    
    1. 测试
    @Test
    public void checkUserLoginByParam() {
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        ParameterMapper sqlSessionMapper = sqlSession.getMapper(ParameterMapper.class);
        User user = sqlSessionMapper.checkUserLoginByParam("法外狂徒", "123456");
        System.out.println(user);
    }
    
    1. 成功

    总结:当使用@Param注解时,Mybatis会将@Param注解的值为键,参数为值存储。sql中可以直接只用@Param注解的值来查询。

    Mybatis会将这些参数放在一个map集合中,以两种方式存储:

    a>以@Param注解的值为键,以参数为值

    b>以param1,param2,…为键,参数为值

    获取参数值大总结

    上方获取参数的5种情况,我们可以整合为2种情况**(非常建议)**:

    1. 实体类对象的情况
    2. 其他情况,全部都用@Param注解
    十、Mybatis各种查询功能 select的返回类型

    上面的例子中,我们查询了用户信息,用户列表…所以我们会为其设置返回类型——User、List

    但是如果我们要查询表中的总记录数该怎么实现呢?

    1. 不指定返回类型
    public interface ParameterMapper {
    	
    	Integer getCount();
    }
    
    
        select count(*) from tbl_user
    
    

    1. 指定返回类型int
    
        select * from tbl_user where id = #{id}
    
    
    1. 测试
    @Test
    public void getUserByIdToMap() {
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        ParameterMapper sqlSessionMapper = sqlSession.getMapper(ParameterMapper.class);
        Map map = sqlSessionMapper.getUserByIdToMap(3);
        System.out.println(map);
    }
    
    1. 成功

    结果存入map集合,会以字段名为键,数据为值,存入map中.

    map的使用场景:

    若我们需要的数据不是从一张表中查询出来的,而是多个表的数据混合而成的,而这时,我们并没有与之相对应的实体类对象,那怎么办呢?

    我们就可以使用一个Map集合存起来。

    十一、特殊sql的执行

    mybatis中有些情况的sql语句必须用${}而不能用#{}

    但是#{}方式能够很大程度防止sql注入,${}方式无法防止Sql注入:

    如果我们order by语句后用了${},那么不做任何处理的时候是存在SQL注入危险的。你说怎么防止,那我只能悲惨的告诉你,你得手动处理过滤一下输入的内容。如判断一下输入的参数的长度是否正常(注入语句一般很长),更精确的过滤则可以查询一下输入的参数是否在预期的参数集合中。

    参考文章:https://www.cnblogs.com/mmzs/p/8398405.html

    处理模糊查询 错误写法
    1. 创建一个mapper接口
    public interface ParameterMapper {
        
        User getUserByLike(@Param("keywords") String keywords);
    }
    
    1. 编写mapper接口对应的方法
    
        select *
        from tbl_user
        where username like '%${keywords}%'
    
    
    
    
        select * from #{tablename}
    
    

    由于 #{} 会自动在两边加上单引号,所以会导致最终sql语句变为:

    select * from 'tablename';
    

    这样就错误了

    正确写法

    所以这种情况也只能使用 ${} 了

    
        select * from ${tablename}
    
    

    再提一次,使用${}的时候要手动防止sql注入,过滤传入参数的内容。

    添加时获取自增的主键

    有时,由于数据表中设置了主键自增策略或者框架中设置了自动生成主键的策略,所以我们在我们要插入一条数据时,可以不指定主键,让它自动生成。

    但是,在有的新增数据功能中,我们在插入数据之后还需要获取自动生成的主键。

    如果再使用一条查询语句去获取的话,就太影响效率了,所以我们需要在插入数据成功之后并得到这个主键。

    1. 创建一个mapper接口
    public interface ParameterMapper {
        
        Integer insertUserGetId(User user);
    }
    
    1. 编写mapper接口对应的方法
    
    
        insert into tbl_user
        values (null, #{username}, #{password}, #{age}, #{sex}, #{email});
    
    
    
    
        insert into tbl_user
        values (123456, #{username}, #{password}, #{age}, #{sex}, #{email});
    
    
    1. 测试
    @Test
    public void insertUserGetId() {
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        ParameterMapper sqlSessionMapper = sqlSession.getMapper(ParameterMapper.class);
        User user = new User(null,"王五","123456",22,"男","123@qq.com");
        Integer insert = sqlSessionMapper.insertUserGetId(user);
        // 直接查询上面传入的user。原来是null,没有值,要看执行完sql语句后,有没有值。
        System.out.println(user);
    }
    
    1. 成功

    useGeneratedKeys:当前标签中使用了自动生成的主键
    keyProperty:将自动生成的主键的值赋值给传输到映射文件中参数的某个属性。

    十二、自定义映射resultMap 引入问题
    1. 新建一个实体类 User2,但是要做一些小操作。把 username --> user ,password --> passwd
    package com.example.pojo;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class User2 {
        private Integer id;
        // username字段对应user
        private String user;
        // password字段对应passwd
        private String passwd;
        private Integer age;
        private String sex;
        private String email;
    }
    
    1. 重新搭建一个 User2Mapper接口 、 User2Mapper.xml 、 User2MapperTest.java
    
        select id,username user,password passwd,age,sex,email from tbl_user
    
    

    方法2:全局配置

    设置全局配置,能够将下划线 _ 自动映射为驼峰(该例子不符合,自行实验)

    即字段 user_name ,能够映射到属性 userName

    1. 在核心配置文件中配置
    
        
    
    
    方法3:resultMap(常用)

    通过resultMap设置自定义的映射关系 (用得最多)

    
    
    
    
        
        
            
            
            
            
            
            
            
            
            
        
    	
        
        select *
        from emp
        left join dept d
        on emp.deptno = d.deptno
        where emp.empno = #{eid}
    
    

    通过association标签

    association:处理多对一的映射关系

    property:需要处理多对的映射关系的属性名

    javaType:该属性的类型

    1. 设置 resultMap 中的标签
    
        
        
        
        
        
        
        
        
        
        
            
            
            
        
    
    
    1. 测试

    分步查询(常用)
    1. 先写resultMap
    
        
        
        
        
        
        
        
        
        
        
        
        
    
    
    1. 编写sql语句
    
    
            select *
            from dept where deptno = #{deptno};
        
    
    
    1. 测试
    @Test
    public void getDeptByEno(){
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
        Emp empAndDept = empMapper.getDeptByEno(7369);
        System.out.println(empAndDept);
    }
    

    说明一下这个是如何执行的?

    1. 首先是执行了 EmpMapper 接口中的 getDeptByEno(7369) 方法
    2. 根据方法,Mybatis执行了 select * from emp where empno = 7369
    3. 查询出来的结果放到了 resultMap 中,基本值都放了进去,随即处理 association标签 中的数据问题
    4. 判断出了是 分步查询 ,所以 select 属性,去执行了 DeptMapper 中的 getEmpAndDeptByStepTwo() 方法,参数是第一步中 column属性 字段所对应的值。
    5. 然后将 getEmpAndDeptByStepTwo() 方法的结果赋值给了 association" 里的 dept 属性
    6. 最终组合完成了 resultMap
    延迟加载

    明明一句sql就能完成的事,为什么要用分步查询,用两步、两句sql来实现呢?

    只写为一句sql,那它可以完成一个完整的功能。若用分步查询,写成两句sql,那这两句sql各自就是一个功能。

    分步查询就可以实现一个 “延迟加载” 的功能,什么是 “延迟加载”?

    如上面的分步查询例子:当我们直接执行 getEmpAndDeptByStepTwo() 这个方法,他会根据部门号返回部门信息。但是如果我们执行 getDeptByEno() 方法的话,他先根据员工号查询员工,然后分步查询,再根据员工号去查询对应的部门信息。

    现在有一个问题,如果我们只想利用 getDeptByEno() 这个方法获取员工姓名,可以,但是第二步就完全没必要了。

    而 “延迟加载” 就是 按需执行。调用分步查询方法,如果你只想获取员工姓名,那么它只会执行第一步;如果你想要获取该员工对应的部门信息,它就会执行两步,获取部门信息。

    1. 延迟加载在 Mybatis 中默认是不开启的。所以需要我们手动开启。在核心配置文件中设置。
    
        
        
        
    
    

    全局设置延迟加载,会使所有的分步查询都是延迟加载。

    若只想设置某个分步查询实现延迟加载,可以:

    1. 比如我们只想要获取用户姓名,那肯定是使用通过员工号获取员工信息的方法。
    
        select *
        from dept
                 left join emp e on dept.deptno = e.deptno
        where e.deptno = #{deptno}
    
    
    1. 编写resultMap
    
        
        
        
        
        
            
            
            
            
            
            
            
            
        
    
    

    collection标签就是专门用来处理一对多的关系的,换句话说collection就是处理集合用的。

    1. 测试
    @Test
    public void getDeptAndEmpTest(){
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class);
        Dept dept = deptMapper.getAllEmp(20);
        System.out.println(dept);
    }
    

    分步查询

    步骤和多对一时的分步查询基本一致。

    1. 先写resultMap
        
            
            
            
            
    
            
        
    
    1. 编写sql语句
    
    
        select *
        from emp
        where deptno = #{deptno}
    
    
    1. 测试
    @Test
    public void getDeptAndEmpByStep(){
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class);
        Dept dept = deptMapper.getDept(20);
        System.out.println(dept);
    }
    

    十三、动态SQL

    Mybatis框架的动态SQL技术是一种根据特定条件动态拼装SQL语句的功能,它存在的意义是为了解决拼接SQL语句字符串时的痛点问题。

    应用场景:多条件查询

    比如在购物网站中,要筛选出你想要的物品,可能会选择多个条件,但也有可能只选择了一个,因为各种条件是可选可不选的,所以前端会把所有条件的选择情况都发送到后端,没选的就是null。但是没有选择的条件是绝对不能出现在我们的sql语句之中的。

    所以我们在多条件查询的时候需要对这些条件进行筛选,条件值为null的就踢出sql语句。

    if

    可以使用标签来写条件,只有当test里面的条件满足时,才会将 if 标签内的sql语句拼接上去。

    test里面的条件中的 且 ,直接用 and 表示

    
        select * from emp
        
            
                ename = #{ename} and
            
            
                deptno = #{deptno}
            
        
    
    
    @Test
    public void getEmpByCondition() {
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        DynamicSQLMapper dynamicSQLMapper = sqlSession.getMapper(DynamicSQLMapper.class);
        Emp emp = new Emp(null, "SMITH", null, null, null, null, null, null, null);
        List empList = dynamicSQLMapper.getEmpByCondition(emp);
        empList.forEach(System.out::println);
    }
    

    当使用 trim 标签后,并设置去掉后面的and或or,那么会自动将最终sql语句中的 and 去掉。

    尝试一个新的情况:把所有条件全部删掉,看看会不会自动去掉where,因为我们设置了前缀where

    @Test
    public void getEmpByCondition() {
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        DynamicSQLMapper dynamicSQLMapper = sqlSession.getMapper(DynamicSQLMapper.class);
        Emp emp = new Emp(null, null, null, null, null, null, null, null, null);
        List empList = dynamicSQLMapper.getEmpByCondition(emp);
        empList.forEach(System.out::println);
    }
    

    若trim中没有条件,也不会自动生成where。

    若标签中有内容时,会按照配置向内容前后添加内容或去掉内容。当标签中没有内容时,trim标签也不会有任何效果。

    choose、when、otherwise

    choose、when、otherwise

    when相当于if … ,else if …

    otherwise相当于else

    choose表示一个完整的if、else if、else结构

    
    

    Mybatis自动将 转换为 deptno,dname,loc

    设置SQL片段:deptno,dname,loc

    引用SQL片段:

    如果以后开发一个mapper.xml,里面有上百条查询语句,字段又多到爆炸,这个方法就很好!!!

    十四、Mybatis的缓存

    Mybatis中的缓存会将我们查询的数据进行缓存,然后这个时候当我们再次去查询的时候,如果缓存中有,就从缓存中拿;如果缓存中没有,再到数据库中去取。注:只对查询功能有效

    一级缓存

    一级缓存是SqlSession级别的,通过同一个SqlSession查询的数据会被缓存,下次查询相同的数据,就会从缓存中直接获取,不会从数据库重新访问。

    @Test
    public void getDeptAndEmpTest() {
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class);
        Dept dept = deptMapper.getAllEmp(20);
        System.out.println(dept);
        Dept dept2 = deptMapper.getAllEmp(20);
        System.out.println(dept2);
    }
    

    只要是通过同一个SqlSession查询出来的数据是会被缓存的。(两个不同mapper,但是同一个SqlSession获取的,也是可以缓存的)

    在Mybatis中,一级缓存是自动开启的。

    使一级缓存失效的四种情况:

    • SqlSession不是同一个
    • 同一个SqlSession但是查询条件不同
    • 同一个SqlSession两次查询期间执行了任何一次增删改操作
    • 同一个SqlSession两次查询期间手动清空了缓存(SqlSession.clearCache())
    二级缓存

    二级缓存是SqlSessionFactory级别的,通过同一个SqlSessionFactory创建的SqlSession查询的结果会被缓存,此后若再次执行相同的查询语句,结果就会从缓存中获取。

    二级缓存开启的条件:

    1. 在核心配置文件中,设置全局配置属性 cacheEnabled=“true”(默认为true,不需要设置)
    2. 在映射文件中设置标签
    3. 二级缓存必须在SqlSession关闭或提交之后有效
    4. 查询的数据所转换的实体类类型必须实现序列化的接口

    使二级缓存失效的情况:

    • 两次查询之间执行的了任意的增删改,会使一级和二级缓存同时失效。
    十五、Mybatis的逆向工程
    • 正向工程:先创建Java实体类,由框架负责根据实体类生成数据表
    • 逆向工程:先创建数据库表,由框架负责根据数据库表**(代码生成器)**,反向生成如下资源:
      • Java实体类
      • Mapper接口
      • Mapper映射文件

    可参考文章:https://blog.csdn.net/qq_52797170/article/details/123969559

    十六、Mybatis的分页插件

    在实际的项目开发中,常常需要使用到分页,分页方式分为两种:前端分页和后端分页。

    前端分页

    一次ajax请求数据的所有记录,然后在前端缓存并且计算count和分页逻辑,一般前端组件(例如dataTable)会提供分页动作。
    特点是:简单,很适合小规模的web平台;当数据量大的时候会产生性能问题,在查询和网络传输的时间会很长。

    后端分页

    在ajax请求中指定页码pageNum和每页的大小pageSize,后端查询出当页的数据返回,前端只负责渲染。
    特点是:复杂一些;性能瓶颈在MySQL的查询性能,这个当然可以调优解决。一般来说,开发使用的是这种方式。

    可参考文章:https://blog.csdn.net/vcj1009784814/article/details/106391982

    参考资源:

    【尚硅谷】2022版MyBatis教程

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

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

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