• mybatis



    文档 :https://mybatis.org/mybatis-3/zh/getting-started.html

    MyBatis 简介

    什么是 mybatis

    MyBatis 是一款优秀的持久层框架。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO为数据库中的记录。

    MyBatis 前身是 IBatis ,本是 Apache 的一个开源项目 ;由apache software foundation 迁移到了google code,并且改名为MyBatis

    实体类和 SQl 语句之间建立映射关系

    MyBatis 优势

    • 半自动化的 ORM 实现
    • DAO 层
    • 动态 SQL
    • 小巧灵活、简单易学

    优点

    • 与JDBC相比,减少了代码量
    • 最简单的持久层框架,小巧并简单易学
    • SQL 从java 代码中分离,可重复使用
    • 提供 xml 标签,支持编写动态 SQL
    • 提供映射标签,支持对象与数据库的 ORM 字段映射

    持久化

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

    也就是将数据存入数据库(永久性的保存下来了)

    ORM (Object Relational Mapping)对象关系映射

    编写程序的时候,以面向对象的方式处理数据

    保存数据的时候,以关系型数据库的方式存储数据

    需要的jar或依赖

    
    <dependency>
        <groupId>org.mybatisgroupId>
        <artifactId>mybatisartifactId>
        <version>3.5.7version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    基本结构搭建

    1、创建一个普通的 maven 项目

    2、将 jar 包或依赖引入项目

    
    <dependency>
        <groupId>org.mybatisgroupId>
        <artifactId>mybatisartifactId>
        <version>3.5.7version>
    dependency>
    
    <dependency>
        <groupId>mysqlgroupId>
        <artifactId>mysql-connector-javaartifactId>
        <version>8.0.25version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    3、在resources文件夹下创建 mybatis-config.xml

    写基本的mybatis 配置,包含了MyBatis 系统的核心设置,包含获取数据库连接实例的数据源(DataSource)和决定事务范围和控制方式的事务管理器(TransactionManager),后面的学习还会往里面继续添加配置。

    
    DOCTYPE configuration
      PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
      "http://mybatis.org/dtd/mybatis-3-config.dtd">
    
    <configuration>
    	
    	<environments default="development">
    		<environment id="development">
    			
    			<transactionManager type="JDBC" />
    			
    			<dataSource type="POOLED">
    				
    				<property name="driver" value="com.mysql.cj.jdbc.Driver" />
    				
    				<property name="url" value="jdbc:mysql://127.0.0.1:3306/smbms?useUnicode=true&characterEncoding=utf8&useSSL=true" />
    				
    				<property name="username" value="root" />
    				
    				<property name="password" value="admin" />
    			dataSource>
    		environment>
    	environments>
    	
    	
    	<mappers>
    		<mapper resource="com/hkp/mapper/UserMapper.xml" />
    	mappers>
    configuration>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    4、编写实体类 User

    package com.hkp.entity;
    
    import java.util.Date;
    
    public class User {
    
      private Integer id;
      private String userCode;
      private String userName;
      private String userPassword;
      private Integer gender;
      private Date birthday;
      private String phone;
      private String address;
      private Integer userRole;
      private Integer createdBy;
      private Date creationDate;
      private Integer modifyBy;
      private Date modifyDate;
    
      @Override
      public String toString() {
        return "User{" +
                "id=" + id +
                ", userCode='" + userCode + '\'' +
                ", userName='" + userName + '\'' +
                ", userPassword='" + userPassword + '\'' +
                ", gender=" + gender +
                ", birthday=" + birthday +
                ", phone='" + phone + '\'' +
                ", address='" + address + '\'' +
                ", userRole=" + userRole +
                ", createdBy=" + createdBy +
                ", creationDate=" + creationDate +
                ", modifyBy=" + modifyBy +
                ", modifyDate=" + modifyDate +
                '}';
      }
    
      public Integer getId() {
        return id;
      }
    
      public void setId(Integer id) {
        this.id = id;
      }
    
      public String getUserCode() {
        return userCode;
      }
    
      public void setUserCode(String userCode) {
        this.userCode = userCode;
      }
    
      public String getUserName() {
        return userName;
      }
    
      public void setUserName(String userName) {
        this.userName = userName;
      }
    
      public String getUserPassword() {
        return userPassword;
      }
    
      public void setUserPassword(String userPassword) {
        this.userPassword = userPassword;
      }
    
      public Integer getGender() {
        return gender;
      }
    
      public void setGender(Integer gender) {
        this.gender = gender;
      }
    
      public Date getBirthday() {
        return birthday;
      }
    
      public void setBirthday(Date birthday) {
        this.birthday = birthday;
      }
    
      public String getPhone() {
        return phone;
      }
    
      public void setPhone(String phone) {
        this.phone = phone;
      }
    
      public String getAddress() {
        return address;
      }
    
      public void setAddress(String address) {
        this.address = address;
      }
    
      public Integer getUserRole() {
        return userRole;
      }
    
      public void setUserRole(Integer userRole) {
        this.userRole = userRole;
      }
    
      public Integer getCreatedBy() {
        return createdBy;
      }
    
      public void setCreatedBy(Integer createdBy) {
        this.createdBy = createdBy;
      }
    
      public Date getCreationDate() {
        return creationDate;
      }
    
      public void setCreationDate(Date creationDate) {
        this.creationDate = creationDate;
      }
    
      public Integer getModifyBy() {
        return modifyBy;
      }
    
      public void setModifyBy(Integer modifyBy) {
        this.modifyBy = modifyBy;
      }
    
      public Date getModifyDate() {
        return modifyDate;
      }
    
      public void setModifyDate(Date modifyDate) {
        this.modifyDate = modifyDate;
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143

    5、编写接口 UserMapper

    public interface UserMapper {
        /**
    	 * 这里的方法名和返回值必须要和xml文件中的名称一样
    	 * 返回值要和resultType中的值一样,这里resultType会自动将user加入list集合
    	 * 方法名要和id 名称一样
    	 * @return
    	 */
        List<User> getUser();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    6、编写接口实现(这里有原来的UserDaoImpl 转换为 UserMapper.xml )

    
    DOCTYPE mapper
      PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
      "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    
    <mapper namespace="com.hkp.mapper.UserMapper">
       
        
        <select id="getUser" resultType="com.hkp.entity.User">
    		select * from smbms_user
    	select>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    7、写测试类,使用 Junit 运行

    package com.hkp.mapper;
    
    import com.hkp.entity.User;
    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.InputStream;
    import java.util.List;
    
    public class TestUserMapper {
        @Test
        public void test() throws Exception {
            //读取mybatis 核心配置文件
            InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
    
            //创建工厂构建器
            SqlSessionFactoryBuilder sqlSessionFactoryBuilder=new SqlSessionFactoryBuilder();
    
            //使用 mybatis 核心配置文件 构建工厂
            SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
    
            //打开 sql 会话(跟数据库打开了一个会话)
            SqlSession sqlSession = sqlSessionFactory.openSession();
    
            //使用sql会话执行sql语句
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            List<User> user = mapper.getUser();
            //关闭会话,释放资源
            sqlSession.close();
    
            //查询到的数据
            System.out.println("查询到的数据 : ");
            for (User user1 : user) {
                System.out.println(user1);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    MyBatis的基本要素

    MyBatis 的核心对象:

    • SqlSessionFactoryBuilder
    • SqlSessionFactory
    • SqlSession

    mybatis-config.xml 是 MyBatis 核心配置文件

    xxxMapper.xml SQL映射文件

    核心对象

    SqlSessionFactoryBuilder

    用过即丢,生命周期只存在方法内

    可以通过 build 方法创建多个 SqlSessionFactory 实例

    SqlSessionFactory

    SqlSessionFactory 是每个 MyBatis 应用的核心

    作用域整个应用

    生命周期与应用的生命周期相同(即软件启动和结束相同)

    作用是创建 SqlSession 实例

    SqlSession sqlSession = sqlSessionFactory.openSession(Boolean boolean);
    
    • 1

    里面的参数可以加也可以不加 默认是 true ;

    true :表示关闭事务控制

    false : 表示开启事务控制

    SqlSession

    包含SQL 执行的所有方法

    对应一次数据库会话,会话结束必须关闭

    SqlSessionFactoryBuilder 和 SqlSessionFactory 在应用中只需要启动一次,SqlSession 可以启动多次 ;所以我们将 SqlSessionFactoryBuilder 和 SqlSessionFactory封装一下。

    MyBatisUtil 工具类的封装

    1、创建工具类

    package com.hkp.utils;
    
    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 java.io.IOException;
    import java.io.InputStream;
    
    public class MyBatisUtil {
        private static SqlSessionFactory sqlSessionFactory;
        //静态代码块,运行时只加载一次
        static {
            // 读取mybatis 核心配置文件
            InputStream inputStream = null;
            try {
                inputStream = Resources.getResourceAsStream("mybatis-config.xml");
            } catch (IOException e) {
                e.printStackTrace();
            }
            // 创建工厂构建器
            SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
            // 使用mybatis 核心配置文件 构建工厂
            sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
        }
        //将方法定义成static静态的,类外部的方法就可以通过类名打点调用该方法了
        public static SqlSession getSqlSession() {
            // 打开 sql 会话(跟数据库打开了一个会话)
            SqlSession sqlSession = sqlSessionFactory.openSession();
            return sqlSession;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    2、测试运行

    package com.hkp.utils;
    
    import com.hkp.entity.User;
    import com.hkp.mapper.UserMapper;
    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    import java.util.List;
    
    public class TestUtil {
        @Test
        public void test() throws Exception {
            SqlSession sqlSession = MyBatisUtil.getSqlSession();
            //使用sql会话执行sql语句     "User.getUser" 配置文件中的命名空间和id
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            List<User> users = userMapper.getUser();
            //关闭会话,释放资源
            sqlSession.close();
            //查询到的数据
            for (User user:users) {
                System.out.println(user);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    核心配置文件

    
    DOCTYPE configuration
      PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
      "http://mybatis.org/dtd/mybatis-3-config.dtd">
    
    <configuration>
    	
    	<environments default="development">
    		<environment id="development">
    			
    			<transactionManager type="JDBC" />
    			
    			<dataSource type="POOLED">
    				
    				<property name="driver" value="com.mysql.cj.jdbc.Driver" />
    				
    				<property name="url" value="jdbc:mysql://127.0.0.1:3306/smbms?useUnicode=true&characterEncoding=utf8&useSSL=true" />
    				
    				<property name="username" value="root" />
    				
    				<property name="password" value="admin" />
    			dataSource>
    		environment>
    	environments>
    	
    	
    	<mappers>
    		<mapper resource="com/hkp/mapper/UserMapper.xml" />
    	mappers>
    configuration>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    属性说明 (注意 :顺序不能反,不然会报错)

    configuration  配置
        properties  可以配置在java属性配置文件中
        settings    修改 Mybatis 在运行时的行为方式
        typeAliases  为java类型命名一个别名 (简称)
        typeHandlers  类型处理器
        ObjectFactory  对象工厂
        plugins    插件
        environments   环境
            environment   环境变量
              transactionManager   事务管理器
              dataSource    数据源
        mappers   映射器
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    重要属性讲解

    properties

    指定外部配置文件,实现动态配置

    好处 :

    jdbc:mysql://127.0.0.1:3306/smbms?useUnicode=true&characterEncoding=utf-8

    在 MyBatis 核心配置文件 也就是 mybatis-config.xml 中不能用 & 符号

    xml 中使用 & 会报错 :转义错误 & 转义是 &

    错误信息如下 :

    在这里插入图片描述

    1、在 resources 文件夹下面创建 db.properties 文件

    driver=com.mysql.cj.jdbc.Driver
    url=jdbc:mysql://127.0.0.1:3306/smbms?useUnicode=true&characterEncoding=utf-8&useSSL=true
    user=root
    password=admin
    
    • 1
    • 2
    • 3
    • 4

    2、将 db.properties 配置文件引入MyBatis 核心配置(mybatis-config.xml)中,核心配置修改完如下 :

    
    DOCTYPE configuration
      PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
      "http://mybatis.org/dtd/mybatis-3-config.dtd">
    
    <configuration>
        
    	<properties resource="db.properties">properties>
    	
    	<environments default="development">
    		<environment id="development">
    			
    			<transactionManager type="JDBC" />
    			
    			<dataSource type="POOLED">
    				
    				<property name="driver" value="${driver}" />
    				
    				<property name="url" value="${url}" />
    				
    				<property name="username" value="${user}" />
    				
    				<property name="password" value="${password}" />
    			dataSource>
    		environment>
    	environments>
    	
    	
    	<mappers>
    		<mapper resource="com/hkp/mapper/UserMapper.xml" />
    	mappers>
    configuration>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    settings – log4j

    用来修改 MyBatis 运行时的行为方式

    主要是 MyBatis 的一些全局配置属性的设置

    这里以配置日志文件为例 :

    1、引入 log4j 的 jar 依赖

    
    <dependency>
        <groupId>log4jgroupId>
        <artifactId>log4jartifactId>
        <version>1.2.17version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2、在 resources 文件夹中创建 log4j.properties 文件 (网上随便找一个即可),放在resource 文件夹下面也行

    ### 配置根 ###
    log4j.rootLogger = debug,console ,fileAppender
    
    ### 设置输出sql的级别,其中logger后面的内容全部为jar包中所包含的包名 ###
    log4j.logger.org.mybatis=debug
    log4j.logger.java.sql.Connection=debug
    log4j.logger.java.sql.Statement=debug
    log4j.logger.java.sql.PreparedStatement=debug
    log4j.logger.java.sql.ResultSet=debug
    
    ### 配置输出到控制台 ###
    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 =  %d{ABSOLUTE} %5p %c{ 1 }:%L - %m%n
    
    ### 配置输出到文件 ###
    log4j.appender.fileAppender = org.apache.log4j.FileAppender
    log4j.appender.fileAppender.File = ./logs/log.log
    log4j.appender.fileAppender.Append = true
    log4j.appender.fileAppender.Threshold = DEBUG
    log4j.appender.fileAppender.layout = org.apache.log4j.PatternLayout
    log4j.appender.fileAppender.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    3、在 MyBatis 核心配置文件 中配置

    
    DOCTYPE configuration
      PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
      "http://mybatis.org/dtd/mybatis-3-config.dtd">
    
    <configuration>
    	
    	<properties resource="db.properties">properties>
    
    	
    	<settings>
    		
    		<setting name="logImpl" value="LOG4J" />
    	settings>
    
    	
    	<environments default="development">
    		<environment id="development">
    			
    			<transactionManager type="JDBC" />
    			
    			<dataSource type="POOLED">
    				
    				<property name="driver" value="${driver}" />
    				
    				<property name="url" value="${url}" />
    				
    				<property name="username" value="${user}" />
    				
    				<property name="password" value="${password}" />
    			dataSource>
    		environment>
    	environments>
    
    	
    	<mappers>
    		<mapper resource="com/hkp/mapper/UserMapper.xml" />
    	mappers>
    configuration>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    typeAliases

    类型别名

    只关联 xml 配置,简写冗长的 java 类名

    两种方法 :单个类配置别名,批量配置别名(扫描包)

    
    <typeAliases>
        
        <typeAlias type="com.hkp.entity.User" alias="user" />
    
        
        <package name="com.hkp.entity"/>
    typeAliases>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    配置完别名在写 SQL 的xml 文件里返回值就可以是别名了,而不再是实体的全路径名了

    核心配置文件修改完如下:

    
    DOCTYPE configuration
      PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
      "http://mybatis.org/dtd/mybatis-3-config.dtd">
    
    <configuration>
    	
    	<properties resource="db.properties">properties>
    
    	
    	<settings>
    		
    		<setting name="logImpl" value="LOG4J" />
    	settings>
        
        
    	<typeAliases>
    		
    		<typeAlias type="com.hkp.entity.User" alias="user" />
    		
    		
    		<package name="com.hkp.entity"/>
    	typeAliases>
    
    	
    	<environments default="development">
    		<environment id="development">
    			
    			<transactionManager type="JDBC" />
    			
    			<dataSource type="POOLED">
    				
    				<property name="driver" value="${driver}" />
    				
    				<property name="url" value="${url}" />
    				
    				<property name="username" value="${user}" />
    				
    				<property name="password" value="${password}" />
    			dataSource>
    		environment>
    	environments>
    
    	
    	<mappers>
    		<mapper resource="com/hkp/mapper/UserMapper.xml" />
    	mappers>
    configuration>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    mappers – 映射器

    注册绑定我们的 Mapper 文件

    方式一 :

    
    <mappers>
      <mapper resource="com/hkp/mapper/UserMapper.xml" />
    mappers>
    
    • 1
    • 2
    • 3
    • 4

    方式二 :

    注意 :接口和mapper配置文件必须同名,也必须在同一包下

    
    <mappers>
      <package name="com.hkp.mapper"/>
    mappers>
    
    • 1
    • 2
    • 3
    • 4

    方式三 :

    注意 :接口和mapper配置文件必须同名,也必须在同一包下

    
    <mappers>
      <mapper class="com.hkp.mapper.UserMapper"/>
    mappers>
    
    • 1
    • 2
    • 3
    • 4

    SQL映射的 xxxMapper.xml 文件

    SQL映射文件就是写SQL的 xml 文件

    SQL映射文件的元素(按照顺序)

    mapper  -  namespace
    	cache   配置给定命名空间的缓存
    	cache-ref   从其他命名空间中引用缓存
    	resultMap   用来描述数据库结果集合对象的关系
    	sql    可以重用的SQL块,也可以被其他语句引用
    	insert/select/delete/update  增删改查  无顺序之分
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    mapper

    namespace 命名空间

    namespace 和增删改查的 id 要确保是唯一的,以区别不同的 mapper 接口和方法

    sql片段

    这个元素可以用来定义可重用的 SQL 代码片段,以便在其它语句中使用。 参数可以静态地(在加载的时候)确定下来,并且可以在不同的 include 元素中定义不同的参数值。比如:

    
    <sql id="userColumns"> ${alias}.id,${alias}.username,${alias}.password sql>
    
    • 1
    • 2

    这个 SQL 片段可以在其它语句中使用,例如:

    <select id="selectUsers" resultType="map">
      select
        <include refid="userColumns"><property name="alias" value="t1"/>include>,
        <include refid="userColumns"><property name="alias" value="t2"/>include>
      from some_table t1
        cross join some_table t2
    select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    案例

    查询用户

    xml

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    
    <mapper namespace="com.hkp.mapper.UserMapper">
    
    	<sql id="getUser">
    		select * from smbms_user where gender = ${gender}
    	sql>
    	
    	<select id="getUser" resultType="com.hkp.entity.User">
    		<include refid="getUser">
    			<property name="gender" value="#{gender}"/>
    		include>
    		LIMIT #{start},#{pageNum}
    	select>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    接口

    package com.hkp.mapper;
    
    import com.hkp.entity.User;
    import org.apache.ibatis.annotations.Param;
    
    import java.util.List;
    
    public interface UserMapper {
       List<User> getUser(@Param("gender") Integer gender,@Param("start") Integer start, @Param("pageNum") Integer pageNum);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    测试

    @Test
    public void test() {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
    
        // 获取 mapper 接口
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    
        int gender = 2;
    
        //条件
        Integer pageNow=1; //第几页
        Integer pageNum=3; //每页几行数据
    
        //将第几页转换为limit 参数(起始下标)
        //起始下标=(页码 - 1)*每页的条数
        Integer start = (pageNow-1)*pageNum;
    
        // 获取接口中的方法
        List<User> user=userMapper.getUser(gender,start,pageNum);
    
        // 关闭会话,释放资源
        sqlSession.close();
    
        //打印结果
        for (User user2 : user) {
            System.out.println(user2);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    在这里插入图片描述

    select

    增删改查的 属性基本都差不多,只不过增删改没有resultType,这里以查询为例

    id

    命名空间中的唯一标识符

    接口中的方法与映射文件中的SQL语句id 要 一 一对应

    parameterType

    传入SQL语句的参数类型

    resultType

    SQL语句返回值类型的完整类名或别名

    单个参数的案例

    以 根据用户名模糊查询用户 为例

    1、修改SQL映射文件

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    
    <mapper namespace="com.hkp.mapper.UserMapper">
        
        
        
       <select id="getUserByName" parameterType="string" resultType="com.hkp.entity.User">
    		select * from smbms_user where userName like concat('%',#{userName},'%')
    	select>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    2、修改mapper 接口中的方法

    package com.hkp.mapper;
    
    import com.hkp.entity.User;
    import java.util.List;
    
    public interface UserMapper {
       /**
        * 这里的方法名和返回值必须要和xml文件中的名称一样
        * 返回值要和resultType中的值一样,这里resultType会自动将user加入list集合
        * 方法名要和id 名称一样
        * 参数类型必须和 SQL映射文件中的传入参数类型一致
        * @return
        */
       List<User> getUserByName(String userName);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    3、运行测试

    @Test
    public void tset() {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        // 获取 mapper 接口
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        // 获取接口中的方法
        String userName="张";
        List<User> user = userMapper.getUserByName(userName);
        // 关闭会话,释放资源
        sqlSession.close();
        // 查询到的数据
        for (User user2 : user) {
            System.out.println(user2);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    多个参数的案例

    以 根据用户名和用户地址模糊查询用户 为例

    多参数传递需要一个注解 @Param(“userName”) 这样SQL映射文件就可以直接使用该名称传参了,而不需要parameterType属性了

    1、修改SQL映射文件

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    
    <mapper namespace="com.hkp.mapper.UserMapper">
        
    	
    	<select id="getUserByNameAndAdress" resultType="com.hkp.entity.User">
    		SELECT
    		 *
    		FROM
    		 smbms_user
    		WHERE
    		 userName LIKE CONCAT( '%', #{userName}, '%' )
    		 AND 
    		 address LIKE CONCAT('%',#{address},'%')
    	select>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    2、修改mapper接口的方法

    package com.hkp.mapper;
    
    import com.hkp.entity.User;
    import org.apache.ibatis.annotations.Param;
    import java.util.List;
    
    public interface UserMapper {
       /**
        * 这里的方法名和返回值必须要和xml文件中的名称一样
        * 返回值要和resultType中的值一样,这里resultType会自动将user加入list集合
        * 方法名要和id 名称一样
        * 多参数传递需要一个注解 @Param("userName") 这样SQL映射文件就可以直接使用该名称传参了,而不需要parameterType属性了
        * @return
        */
       List<User> getUserByNameAndAdress(@Param("userName") String userName, @Param("address") String address);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    3、测试运行

    @Test
    public void tset() {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        // 获取 mapper 接口
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        // 获取接口中的方法
        String userName="李";
        String address="北京市";
        List<User> user = userMapper.getUserByNameAndAdress(userName,address);
        // 关闭会话,释放资源
        sqlSession.close();
        // 查询到的数据
        for (User user2 : user) {
            System.out.println(user2);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    封装为对象传递参数的案例

    以 实体类 形式传递

    这里还是以 根据用户名和用户地址模糊查询用户 为例

    以实体类的形式传参,不需要注解,也不需要parameterType属性,只需要跟实体类中的属性名保持一致就行

    1、修改SQL 映射文件

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    
    <mapper namespace="com.hkp.mapper.UserMapper">
        
    	
    	
    	<select id="getUserByNameAndAdress" resultType="com.hkp.entity.User">
    		SELECT
    		 *
    		FROM
    		 smbms_user
    		WHERE
    		 userName LIKE CONCAT( '%', #{userName}, '%' )
    		 AND 
    		 address LIKE CONCAT('%',#{address},'%')
    	select>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    2、修改mapper 接口中的方法

    package com.hkp.mapper;
    
    import com.hkp.entity.User;
    import org.apache.ibatis.annotations.Param;
    import java.util.List;
    
    public interface UserMapper {
       /**
        * 这里的方法名和返回值必须要和xml文件中的名称一样
        * 返回值要和resultType中的值一样,这里resultType会自动将user加入list集合
        * 方法名要和id 名称一样
        * 以实体类的形式传参,不需要注解,也不需要parameterType属性,只需要SQL映射文件中的参数跟实体类中的属性名保持一致就行
        * @return
        */
       List<User> getUserByNameAndAdress(User user);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    3、测试运行

    @Test
    public void tset() {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        // 获取 mapper 接口
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        // 获取接口中的方法
        String userName="李";
        String address="北京市";
        List<User> user = userMapper.getUserByNameAndAdress(userName,address);
        // 关闭会话,释放资源
        sqlSession.close();
        // 查询到的数据
        for (User user2 : user) {
            System.out.println(user2);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    以map的形式传参

    以 查询前三条的用户信息 为例

    以封装map集合的形式传参,不需要注解,也不需要parameterType属性,只需要跟map中的键名保持一致就行

    1、修改SQL映射文件

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    
    <mapper namespace="com.hkp.mapper.UserMapper">
    	
    	
    	
    	<select id="getUserLimit" resultType="com.hkp.entity.User">
    		select * from smbms_user limit #{start},#{end}
    	select>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    2、修改mapper 接口中的方法

    package com.hkp.mapper;
    
    import com.hkp.entity.User;
    import java.util.List;
    import java.util.Map;
    
    public interface UserMapper {
       /**
        * 这里的方法名和返回值必须要和xml文件中的名称一样
        * 返回值要和resultType中的值一样,这里resultType会自动将user加入list集合
        * 方法名要和id 名称一样
        * 以封装map集合的形式传参,不需要注解,也不需要parameterType属性,只需要跟map中的键 名保持一致就行
        * @return
        */
       List<User> getUserLimit(Map<String, Object> map);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    3、测试运行

    @Test
    public void tset() {
    
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
    
        // 获取 mapper 接口
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    
        // 获取接口中的方法
        Map<String, Object> map=new HashMap<String, Object>();
        map.put("start", 0);
        map.put("end",3);
    
        List<User> user = userMapper.getUserLimit(map);
    
        // 关闭会话,释放资源
        sqlSession.close();
    
        // 查询到的数据
        for (User user2 : user) {
            System.out.println(user2);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    自定义映射 ResultMap (返回值类型)

    返回值类型是普通类型的 我们可以使用 ResultType 来写,但是对于复杂的返回值类型怎么返回?使用自定义的 ResultMap

    例如 :想返回 用户id、用户名称、用户性别、用户手机、和角色名称

    这里可以看出,我们需要使用两张表联查(用户表和角色表)

    ResultType :直接返回数据类型 (基本数据类型、复杂数据类型)

    ResultMap :对外部 自定义的映射方式引用

    应用场景:

    • 数据库字段与实体属性不一致

    • 复杂联合查询,可以自由控制映射

    设置resultMap的映射级别

    在核心配置文件中添加:

    
    <settings>		
        
        
        <setting name="autoMappingBehavior" value="PARTIAL"/>
    settings>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    如果在核心配置文件中配置了取消自动映射 ;则在SQL映射文件中就要使用使用自定义的映射ResultMap ;映射只针对查询返回的字段与实体中的属性映射

    如果ResultMap 中出现了association 和collection 标签 ,默认的自动映射无效PARTIAL ,必须配置映射才能完成映射 ;想要自动映射可以使用 FULL 级别 来完成自动映射

    案例

    以查询用户列表 包含(用户id、用户名称、用户性别、用户手机、和角色名称)为例

    mybatis默认的映射机制,根据SQL查询到的字段自动去返回类型中寻找相对应的属性名,根据get 和set 方法进行赋值

    用户表中没有角色名称的,为了可以映射的上,在User实体中添加一个roleName属性

    如果字段名和属性名一致的话,就直接返回就行,如果不一致,则需要使用自定义返回类型ResultMap

    1、在用户实体类中添加一个属性,并添加get和set方法和toString,用于放角色名称

    private String roleName;
    
    • 1

    2、修改SQL映射文件

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    
    <mapper namespace="com.hkp.mapper.UserMapper">
    	
    	
    	
    	<select id="getUser" resultMap="getUserMap">
    		SELECT
    			us.id,
    			us.userName,
    			us.gender,
    			us.phone,
    			role.roleName
    		FROM
    			smbms_user us
    			LEFT JOIN smbms_role role ON us.userRole = role.id
    	select>
    	
    	
    	<resultMap type="com.hkp.entity.User" id="getUserMap">
    		<id column="id" property="id"/>
    		
    		<result column="roleName" property="roleName"/>
    		
    	resultMap>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    3、修改 mapper 接口中的方法

    package com.hkp.mapper;
    
    import com.hkp.entity.User;
    import java.util.List;
    
    public interface UserMapper {
       /**
        * 这里的方法名和返回值必须要和xml文件中的名称一样
        * 返回值要和resultType中的值一样,这里resultType会自动将user加入list集合
        * 方法名要和id 名称一样
        * @return
        */
       List<User> getUser();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    4、测试运行

    @Test
    public void tset() {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        // 获取 mapper 接口
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        // 获取接口中的方法
        List<User> user = userMapper.getUser();
        // 关闭会话,释放资源
        sqlSession.close();
        // 查询到的数据
        for (User user2 : user) {
            System.out.println(user2);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    增删改

    增加、修改和删除 都很类似,他们中都没有resultType 返回值类型,因为他们三个都是影响数据库的行数的,所以返回值默认都是 int 类型

    增删改都需要提交

    sqlSession.commit();
    
    • 1

    增加

    1、修改SQL映射文件

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    
    <mapper namespace="com.hkp.mapper.UserMapper">
    	
    	
    	<insert id="addUser">
    		INSERT INTO `smbms`.`smbms_user` ( `userName`, `userPassword`, `address` )
    		VALUES(#{userName},#{userPassword},#{address});
    	insert>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    2、修改mapper 接口中的方法

    package com.hkp.mapper;
    
    import com.hkp.entity.User;
    
    public interface UserMapper {
       /**
        * 这里的方法名和返回值必须要和xml文件中的名称一样
        * 方法名要和id 名称一样
        * @return
        */
       int addUser(User user);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    3、测试运行 (增删改都需要提交)

    @Test
    public void test() {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        // 获取 mapper 接口
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        // 获取接口中的方法
        User u=new User();
        u.setUserName("测试");
        u.setUserPassword("test");
        u.setAddress("测试");
        int count = userMapper.addUser(u);
        //增删改 影响数据库的操作需要做提交操作
        sqlSession.commit();
        // 关闭会话,释放资源
        sqlSession.close();
        // 查询到的数据
        System.out.println("影响数据库行数 :"+count);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    修改

    1、修改SQL映射文件

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    
    <mapper namespace="com.hkp.mapper.UserMapper">
    	
    	
    	<update id="updateUser">
    		UPDATE `smbms`.`smbms_user` 
    		SET `userName` = #{userName},
    		`userPassword` = #{userPassword},
    		`address` = #{address}
    		WHERE
    			`id` = #{id};
    	update>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    2、修改mapper 接口中的方法

    package com.hkp.mapper;
    
    import com.hkp.entity.User;
    
    public interface UserMapper {
        /**
    	 * 这里的方法名和返回值必须要和xml文件中的名称一样
    	 * 方法名要和id 名称一样
    	 * @return
    	 */
        int updateUser(User user);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    3、测试运行 (增删改都需要提交)

    @Test
    public void test() {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        // 获取 mapper 接口
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        // 获取接口中的方法
        User u=new User();
        u.setId(16);
        u.setUserName("测试udpate");
        u.setUserPassword("test");
        u.setAddress("测试");
        int count = userMapper.updateUser(u);
        //增删改 影响数据库的操作需要做提交操作
        sqlSession.commit();
        // 关闭会话,释放资源
        sqlSession.close();
        // 查询到的数据
        System.out.println("影响数据库行数 :"+count);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    删除

    1、修改SQL映射文件

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    
    <mapper namespace="com.hkp.mapper.UserMapper">
    	
    	
    	<delete id="delUser" parameterType="int">
    		DELETE FROM smbms_user WHERE id=#{id}
    	delete>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    2、修改mapper 接口中的方法

    package com.hkp.mapper;
    
    import com.hkp.entity.User;
    
    public interface UserMapper {
        /**
    	 * 这里的方法名和返回值必须要和xml文件中的名称一样
    	 * 方法名要和id 名称一样
    	 * @return
    	 */
        int delUser(int id);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    3、测试运行 (增删改都需要提交)

    @Test
    public void test() {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        // 获取 mapper 接口
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        // 获取接口中的方法
        int count = userMapper.delUser(16);
        //增删改 影响数据库的操作需要做提交操作
        sqlSession.commit();
        // 关闭会话,释放资源
        sqlSession.close();
        // 查询到的数据
        System.out.println("影响数据库行数 :"+count);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    MyBatis 映射方式

    resultMap

    SQL映射文件中的一个重要的标签

    resultMap 的属性

    id : resultMap 的唯一标识

    type : java实体类

    resultMap 的子元素

    id :一般对应数据库中的主键,设置此项可以提高 MyBatis 的性能

    result :映射到 javaBean 的某个“简单类型”属性

    association :一对一映射 ,里面放一的一方

    collection :一对多映射,里面放多的一方

    一对一映射

    association :一对一映射 ,里面放一的一方

    属性 :

    property :实体对象属性

    javaType :完整java 类名或别名

    resultMap : 引用外部的resultMap 结果集,使用这个就不需要 javaType 了因为在 resultMap 里面有type属性了

    案例 :

    查询用户列表为例 (包含用户ID、用户名称,用户手机号,角色ID、角色名称)

    1、在User实体中声明Role实体类型,并生成get 和set 以及toString 方法

    private Role role;
    
    • 1

    2、修改SQL映射文件

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    
    <mapper namespace="com.hkp.mapper.UserMapper">
    	<select id="getUser" resultMap="getUserMap">
    		SELECT
    		us.id,
    		us.userName,
    		us.phone,
    		role.id roleId,
    		role.roleName
    		FROM
    		smbms_user us
    		LEFT JOIN smbms_role role ON us.userRole = role.id
    	select>
    	<resultMap type="com.hkp.entity.User" id="getUserMap">
    		<id column="id" property="id" />
    		<result column="userName" property="userName" />
    		<result column="phone" property="phone" />
    		
    		<association property="role" javaType="com.hkp.entity.Role">
    			
    			<id column="roleId" property="id" />
    			<result column="roleName" property="roleName" />
    		association>
    	resultMap>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    3、修改mapper 接口中的方法

    package com.hkp.mapper;
    
    import java.util.List;
    import com.hkp.entity.User;
    
    public interface UserMapper {
    	/**
    	 * 这里的方法名和返回值必须要和xml文件中的名称一样
    	 * 方法名要和id 名称一样
    	 * @return
    	 */
    	List<User> getUser();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    4、测试运行

    @Test
    public void test() {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        // 获取 mapper 接口
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        // 获取接口中的方法
        List<User> list=userMapper.getUser();
        // 关闭会话,释放资源
        sqlSession.close();
        // 查询到的数据
        for (User user : list) {
            System.out.println(user);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    一对多映射

    collection :一对多映射,里面放多的一方

    属性 :

    property :实体对象属性

    ofType :完整java 类名或别名

    resultMap : 引用外部的resultMap 结果集,使用这个就不需要 javaType了因为在 resultMap 里面有type属性了

    案例 :

    查询用户列表为例,一个用户有多个地址

    1、在User实体中声明address实体类型,并生成get 和set 以及toString 方法

    private List<Address> userAddress;
    
    • 1

    2、修改SQL映射文件

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    
    <mapper namespace="com.hkp.mapper.UserMapper">
    	<select id="getUser" resultMap="UserAddressMap">
    		SELECT
    		us.id,
    		us.userName,
    		us.phone,
    		sa.id addressId,
    		sa.contact,
    		sa.addressDesc
    		FROM
    		smbms_user us
    		LEFT JOIN smbms_address sa ON us.id = sa.userId
    	select>
    	<resultMap type="com.hkp.entity.User" id="UserAddressMap">
    		<id column="id" property="id" />
    		<result column="userName" property="userName" />
    		<result column="phone" property="phone" />
    		
    		<collection property="userAddress" resultMap="addressMap" />
    	resultMap>
    	<resultMap type="com.hkp.entity.Address" id="addressMap">
    		<id column="addressId" property="id" />
    		<result column="contact" property="contact" />
    		<result column="addressDesc" property="addressDesc" />
    	resultMap>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    3、修改mapper 接口中的方法

    package com.hkp.mapper;
    
    import java.util.List;
    import com.hkp.entity.User;
    
    public interface UserMapper {
    	/**
    	 * 这里的方法名和返回值必须要和xml文件中的名称一样
    	 * 方法名要和id 名称一样
    	 * @return
    	 */
    	List<User> getUser();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    4、测试运行

    @Test
    public void test() {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        // 获取 mapper 接口
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        // 获取接口中的方法
        List<User> list=userMapper.getUser();
        // 关闭会话,释放资源
        sqlSession.close();
        // 查询到的数据
        for (User user : list) {
            System.out.println(user);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    缓存

    每次发送一次SQL请求都需要去调用数据库,有点太耗资源,速度也慢了 ;

    在第一次发送SQL请求时,从数据库拿到数据,往缓存里保存一份,这样,下次同样的SQL语句,就不去数据库里拿数据了,直接从缓存里拿数据即可,这样也提高了查询速度

    MyBatis 缓存分为 :一级缓存和二级缓存

    一级缓存默认是开启的

    一级缓存

    MyBatis 默认是开启一级缓存的

    在同一个SQL会话(sqlsession)中,执行相同的SQL语句,第二次直接从缓存中获取数据

    作用域 :同一个SQL会话中

    案例

    1、修改SQL映射文件

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    
    <mapper namespace="com.hkp.mapper.UserMapper">
    	<select id="getUser" resultType="com.hkp.entity.User">
    		SELECT * FROM smbms_user
    	select>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    2、修改mapper 接口中的方法

    package com.hkp.mapper;
    
    import com.hkp.entity.User;
    import java.util.List;
    
    public interface UserMapper {
       /**
        * 这里的方法名和返回值必须要和xml文件中的名称一样
        * 返回值要和resultType中的值一样,这里resultType会自动将user加入list集合
        * 方法名要和id 名称一样
        * @return
        */
       List<User> getUser();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    3、测试运行

    @Test
    public void test() {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        // 获取 mapper 接口
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        // 获取接口中的方法
        List<User> list=userMapper.getUser();
        System.out.println("第一次查询已结束");
        List<User> list2=userMapper.getUser();
        System.out.println("第二次查询已结束");
        // 关闭会话,释放资源
        sqlSession.close();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    结果可以发现,两条SQL语句之间没有再去请求数据库,只请求了一次数据库

    在这里插入图片描述

    二级缓存

    MyBatis 二级缓存默认是关闭的

    之前说过 :一级缓存 的作用域只是一个 SQL 会话,那么SQL会话一旦关闭了,再去访问同一个SQL还是要去数据库拿数据的 ;这时候就用到了二级缓存

    二级缓存作用域 :整个命名空间(namespace)中,也就是整个SQL映射文件中

    执行相同的SQL语句,第二次直接从缓存中获取数据

    <cache eviction="FIFO" flushInterval="60000" size="512"
    		   readOnly="true" />
    
    • 1
    • 2

    这个更高级的配置创建了一个 FIFO 缓存,每隔 60 秒刷新,最多可以存储结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此对它们进行修改可能会在不同线程中的调用者产生冲突。

    可用的清除策略有:

    • LRU – 最近最少使用:移除最长时间不被使用的对象。
    • FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
    • SOFT – 软引用:基于垃圾回收器状态和软引用规则移除对象。
    • WEAK – 弱引用:更积极地基于垃圾收集器状态和弱引用规则移除对象。

    默认的清除策略是 LRU。

    flushInterval(刷新间隔)属性可以被设置为任意的正整数,设置的值应该是一个以毫秒为单位的合理时间量。 默认情况是不设置,也就是没有刷新间隔,缓存仅仅会在调用语句时刷新。

    size(引用数目)属性可以被设置为任意正整数,要注意欲缓存对象的大小和运行环境中可用的内存资源。默认值是 1024。

    readOnly(只读)属性可以被设置为 true 或 false。只读的缓存会给所有调用者返回缓存对象的相同实例。 因此这些对象不能被修改。这就提供了可观的性能提升。而可读写的缓存会(通过序列化)返回缓存对象的拷贝。 速度上会慢一些,但是更安全,因此默认值是 false。

    案例

    1、在SQL映射文件中添加配置,开启二级缓存

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    
    <mapper namespace="com.hkp.mapper.UserMapper">
    
    	
    	
    	<cache eviction="FIFO" flushInterval="60000" size="512"
    		   readOnly="true" />
    	
    	<select id="getUser" resultType="com.hkp.entity.User">
    		SELECT * FROM smbms_user
    	select>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    2、mapper 接口方法和一级缓存的方法一样,没有发生改变

    3、测试运行

    @Test
    public void test() {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
    
        // 获取 mapper 接口
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    
        // 获取接口中的方法
        List<User> list=userMapper.getUser();
        System.out.println("第一次查询已结束");
    
        List<User> list2=userMapper.getUser();
        System.out.println("第二次查询已结束");
        // 关闭会话,释放资源
        sqlSession.close();	
        //重新获取sqlsession会话,以及缓存已经失效
        SqlSession sqlSession2 = MyBatisUtil.getSqlSession();
        // 获取 mapper 接口
        UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);	
        //第三次查询用户列表,sqlsession会话已经关闭,一级缓存已经失效
        List<User> list3=userMapper2.getUser();
        System.out.println("第三次查询已结束");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    可以看到前两次查询用户列表是在同一个SQL会话里进行的,此时一级缓存是生效的;而第三次查询用户列表的时候,SQL会话已经关闭了,我们需要重新打开一个SQL会话,因为二级缓存已经被我们开启了,所以第三次查询虽然重新打开了SQL会话,但SQL语句没有发生变化,所以还是走的缓存

    在这里插入图片描述

    二级缓存的作用域是整个SQL映射文件,所以在那个SQL映射文件下面的所有方法都会走缓存,那么有的方法不想走缓存怎么办 ?

    在方法上添加属性 useCache=“false”

    <select id="getUser" resultType="com.hkp.entity.User" useCache="false"> 	
        SELECT * FROM smbms_user 
    select>
    
    • 1
    • 2
    • 3

    这样 二级缓存 对这个方法就不生效了,但一级缓存生效,也就是在同一个SQL会话中执行两次这个SQL,还是会有缓存的(一级缓存)

    在这里插入图片描述

    动态SQL

    基于 OGNL 表达式

    完成多条件查询等逻辑实现

    主要元素有 :

    if、trim、where、set、choose ( when 、 otherwise )、foreach

    if 通常与where 一起使用

    if

    根据条件判断 来增加查询条件

    案例

    根据 用户名和角色ID 来查询用户列表

    1、添加SQL映射文件

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    
    <mapper namespace="com.hkp.mapper.UserMapper">
    
    	<select id="getUser" resultType="com.hkp.entity.User">
    		SELECT * FROM smbms_user
    		WHERE 1=1
    		<if test="userName!=null and userName!=''">
    			AND userName LIKE CONCAT('%',#{userName},'%')
    		if>
    		<if test="userRole!=null">
    			AND userRole = #{userRole}
    		if>
    	select>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    2、添加mapper 接口中的方法

    package com.hkp.mapper;
    
    import java.util.List;
    import org.apache.ibatis.annotations.Param;
    import com.hkp.entity.User;
    
    public interface UserMapper {
    	List<User> getUser(@Param("userName") String userName,@Param("userRole") Integer userRole);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3、测试运行

    @Test
    public void test() {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        // 获取 mapper 接口
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        // 获取接口中的方法
        Integer userRole=3;
        String userName="张";
        List<User> list=userMapper.getUser(userName,userRole);
        // 关闭会话,释放资源
        sqlSession.close();
        //打印结果
        for (User user : list) {
            System.out.println(user);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    where

    动态拼接多个条件,如果没有条件,where 会自动去掉;如果多个条件,where 会自动去掉第一个条件前面的 AND 或 OR

    动态处理 AND 和 OR

    案例

    根据 用户名和角色ID 来查询用户列表

    1、添加SQL映射文件

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    
    <mapper namespace="com.hkp.mapper.UserMapper">
    
    	<select id="getUser" resultType="com.hkp.entity.User">
    		SELECT * FROM smbms_user
    		<where>
    			<if test="userName!=null and userName!=''">
    				AND userName LIKE CONCAT('%',#{userName},'%')
    			if>
    			<if test="userRole!=null">
    				AND userRole = #{userRole}
    			if>
    		where>
    	select>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    2、添加mapper 接口中的方法

    package com.hkp.mapper;
    
    import com.hkp.entity.User;
    import org.apache.ibatis.annotations.Param;
    import java.util.List;
    
    public interface UserMapper {
       List<User> getUser(@Param("userName") String userName,@Param("userRole") Integer userRole);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3、测试运行

    @Test
    public void test() {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
    
        // 获取 mapper 接口
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    
        // 获取接口中的方法
        Integer userRole=null;
        String userName=null;
        List<User> list=userMapper.getUser(userName,userRole);
    
        // 关闭会话,释放资源
        sqlSession.close();
    
        //打印结果
        for (User user : list) {
            System.out.println(user);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    set

    在修改数据的时候,如果值为null ,数据库的信息将会被修改为null;set 可以去处理,如果为null 则不修改,保持数据库中的数据不动

    主要用于修改数据的SQL语句中

    可以动态处理多余的逗号

    案例

    set 的使用方法和 where 类似

    1、添加SQL 映射文件

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    
    <mapper namespace="com.hkp.mapper.UserMapper">
    
    	<update id="updateUser">
    		UPDATE `smbms`.`smbms_user`
    		<set>
    			<if test="userName!=null and userName!=''">
    				`userName` = #{userName},
    			if>
    			<if test="gender!=null">
    				`gender` = #{gender},
    			if>
    			<if test="address!=null and address!=''">
    				`address` = #{address},
    			if>
    		set>
    		WHERE
    		`id` = #{id};
    	update>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    2、添加mapper 接口中的方法

    package com.hkp.mapper;
    
    import com.hkp.entity.User;
    
    public interface UserMapper {
       int updateUser(User user);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    3、测试运行

    @Test
    public void test() {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
    
        // 获取 mapper 接口
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    
        // 获取接口中的方法
        User u=new User();
        u.setId(15);
        u.setUserName("测试");
        u.setGender(1);
        int count=userMapper.updateUser(u);
    	sqlSession.commit();
        // 关闭会话,释放资源
        sqlSession.close();
    
        //打印结果
        System.out.println("影响的行数 :"+count);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    trim

    主要用于更加复杂的SQL语句

    可以替代 where 和 set

    更灵活的去掉多余的关键字

    属性 :

    • prefix : 前缀
    • suffix : 后缀
    • prefixOverrides :前缀覆盖
    • suffixOverrides :后缀覆盖

    案例一 :trim 替换 set

    1、修改SQL映射文件

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    
    <mapper namespace="com.hkp.mapper.UserMapper">
    
    	<update id="updateUser">
    		UPDATE `smbms`.`smbms_user`
    		<trim prefix="set" suffix="WHERE `id` = #{id}" suffixOverrides=",">
    			<if test="userName!=null and userName!=''">
    				`userName` = #{userName},
    			if>
    			<if test="gender!=null">
    				`gender` = #{gender},
    			if>
    			<if test="address!=null and address!=''">
    				`address` = #{address},
    			if>
    		trim>
    	update>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    2、mapper 接口方法与set中的一样,不需要改动

    3、测试运行,代码和 set 中的一样,不需要改动

    案例二 :trim 替代 where

    1、修改SQL映射文件

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    
    <mapper namespace="com.hkp.mapper.UserMapper">
    
    	<select id="getUser" resultType="com.hkp.entity.User">
    		SELECT * FROM smbms_user
    		<trim prefix="where" prefixOverrides="and">
    			<if test="userName!=null and userName!=''">
    				AND userName LIKE CONCAT('%',#{userName},'%')
    			if>
    			<if test="userRole!=null">
    				AND userRole = #{userRole}
    			if>
    		trim>
    	select>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    2、mapper 接口方法与 where 中的一样,不需要改动

    3、测试运行,代码和 where 中的一样,不需要改动

    foreach

    迭代一个集合,通常用于 in 条件

    属性 :

    • item 声明变量去接收元素

    • collection : 必须指定 用来接参数

      • list 接收参数为 list 数组(动态数组 ArrayList)
      • array 接收参数为 array 普通数组
      • map-key 接收参数为 map 集合 ,map集合中数组的key 名称
    • open 以什么开头

    • separator 元素的分隔符

    • close 以什么结尾

    为了方便理解,采用java中的foreach来对比 :

    for (User user : list) {
    	System.out.println(user);
    }
    
    其中 :
    User  相当于  collection  
    user  相当于  item  
    list  相当于  collection 中的值 ( list、array、map-key )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    foreach 遍历普通数组和动态数组都不常用,将数组封装到map 集合中比较常用

    因为 :我们以后传参不可能只穿一个类型的参数(数组中的值是单一类型的),而map集合可以封装很多参数类型来进行传参

    将数组封装到 map 集合中,我们在SQL映射文件 通过集合对应的键名称 来取

    foreach 迭代 一共有三个案例

    普通数组和动态数组 :主要是迭代 in 中的单一类型的参数

    map 集合 :在迭代 in 中的单一类型的参数基础上,加上其他的参数

    案例一 :foreach 迭代普通数组

    1、添加SQL映射文件内容

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    
    <mapper namespace="com.hkp.mapper.UserMapper">
    
    	<select id="getUser" resultType="com.hkp.entity.User">
    		SELECT * FROM smbms_user WHERE id IN
    		<foreach collection="array" item="id" open="(" separator="," close=")">
    			#{id}
    		foreach>
    	select>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    2、添加mapper 接口方法

    package com.hkp.mapper;
    
    import com.hkp.entity.User;
    import java.util.List;
    
    public interface UserMapper {
       List<User> getUser(int[] idArr);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3、测试运行

    @Test
    public void test() {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        // 获取 mapper 接口
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        //创建一个普通的数组
        int[] idArr = {1,2,5};
        // 获取接口中的方法
        List<User> user=userMapper.getUser(idArr);
        // 关闭会话,释放资源
        sqlSession.close();
        //打印结果
        for (User user2 : user) {
            System.out.println(user2);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    案例二 :foreach 迭代动态数组 ArrayList

    1、修改SQL映射文件

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    
    <mapper namespace="com.hkp.mapper.UserMapper">
    
    	<select id="getUser" resultType="com.hkp.entity.User">
    		SELECT * FROM smbms_user WHERE id IN
    		<foreach collection="list" item="id" open="(" separator="," close=")">
    			#{id}
    		foreach>
    	select>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    2、修改mapper 接口中的方法

    package com.hkp.mapper;
    
    import com.hkp.entity.User;
    import java.util.List;
    
    public interface UserMapper {
       List<User> getUser(List<Integer> arrayList);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3、测试运行

    @Test
    public void test() {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
    
        // 获取 mapper 接口
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    
        //创建一个动态的list的数组
        ArrayList<Integer> arrayList = new ArrayList<Integer>();
        arrayList.add(1);
        arrayList.add(2);
    
        // 获取接口中的方法
        List<User> user=userMapper.getUser(arrayList);
    
        // 关闭会话,释放资源
        sqlSession.close();
    
        //打印结果
        for (User user2 : user) {
            System.out.println(user2);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    案例三 :foreach 迭代 map 集合

    1、修改SQL映射文件

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    
    <mapper namespace="com.hkp.mapper.UserMapper">
    
    	<select id="getUser" resultType="com.hkp.entity.User">
    		SELECT * FROM smbms_user WHERE id IN
    		<foreach collection="idList" item="id" open="(" separator="," close=")">
    			#{id}
    		foreach>
    		AND gender = #{gender}
    	select>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    2、修改mapper 接口中的方法

    package com.hkp.mapper;
    
    import com.hkp.entity.User;
    import java.util.List;
    import java.util.Map;
    
    public interface UserMapper {
       List<User> getUser(Map<String, Object> map);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3、测试运行

    @Test
    public void test() {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
    
        // 获取 mapper 接口
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    
        //创建一个动态的list的数组
        ArrayList<Integer> arrayList = new ArrayList<Integer>();
        arrayList.add(1);
        arrayList.add(2);
    
        //将数组封装到集合中
        Map<String, Object> map=new HashMap<String, Object>();
        map.put("idList", arrayList);
        //将其他参数封装到map集合里面
        map.put("gender", 2);
    
        // 获取接口中的方法
        List<User> user=userMapper.getUser(map);
    
        // 关闭会话,释放资源
        sqlSession.close();
    
        //打印结果
        for (User user2 : user) {
            System.out.println(user2);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    choose (when 、otherwise )

    相当于 java 中的switch 语句,当when 有条件满足时,就跳出choose ;如果when 条件都不满足,就执行 otherwise

    案例

    通过 用户名称、用户性别、用户角色id 查询用户列表 ;

    choose 的作用就是选择一个条件去查询

    1、修改SQL映射文件内容

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    
    <mapper namespace="com.hkp.mapper.UserMapper">
    
    	<select id="getUser" resultType="com.hkp.entity.User">
    		SELECT
    		*
    		FROM
    		smbms_user
    		<where>
    			<choose>
    				<when test="userName!=null and userName!=''">
    					AND userName LIKE CONCAT( '%',#{userName}, '%' )
    				when>
    				<when test="gender!=null">
    					AND gender = #{gender}
    				when>
    				<otherwise>
    					AND userRole = #{userRole}
    				otherwise>
    			choose>
    		where>
    	select>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    2、修改mapper 接口中的方法

    package com.hkp.mapper;
    
    import com.hkp.entity.User;
    import java.util.List;
    
    public interface UserMapper {
       List<User> getUser(User user);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3、测试运行

    @Test
    public void test() {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
    
        // 获取 mapper 接口
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    
        // 获取接口中的方法
        User u=new User();
        u.setUserName("赵");
        u.setGender(1);
        u.setUserRole(3);
        List<User> user=userMapper.getUser(u);
    
        // 关闭会话,释放资源
        sqlSession.close();
    
        //打印结果
        for (User user2 : user) {
            System.out.println(user2);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    在这里插入图片描述

    分页

    案例

    1、修改SQL映射文件内容

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    
    <mapper namespace="com.hkp.mapper.UserMapper">
    
    	<select id="getUser" resultType="com.hkp.entity.User">
    		SELECT
    			* 
    		FROM
    			smbms_user 
    		LIMIT #{start},#{pageNum}
    	select>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    2、修改mapper 接口的方法

    package com.hkp.mapper;
    
    import com.hkp.entity.User;
    import org.apache.ibatis.annotations.Param;
    
    import java.util.List;
    
    public interface UserMapper {
       List<User> getUser(@Param("start") Integer start, @Param("pageNum") Integer pageNum);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    3、测试运行

    @Test
    public void test() {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
    
        // 获取 mapper 接口
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    
        //条件
        Integer pageNow=1; //第几页
        Integer pageNum=3; //每页几行数据
    
        //将第几页转换为limit 参数(起始下标)
        //起始下标=(页码 - 1)*每页的条数
        Integer start = (pageNow-1)*pageNum;
    
        // 获取接口中的方法
        List<User> user=userMapper.getUser(start,pageNum);
    
        // 关闭会话,释放资源
        sqlSession.close();
    
        //打印结果
        for (User user2 : user) {
            System.out.println(user2);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    rowbounds 实现分页

    SQL映射文件的内容

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    
    <mapper namespace="com.hkp.mapper.UserMapper">
    	<select id="getUser" resultType="user">
    		select * from smbms_user
    	select>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    接口中的方法

    package com.hkp.mapper;
    
    import com.hkp.entity.User;
    import java.util.List;
    
    public interface UserMapper {
       List<User> getUser();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    测试

    @Test
    public void test() {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
    
        //第一个参数为 第几页,第二个参数为页面有几条数据
        RowBounds rowBounds = new RowBounds(1, 3);
    
        // 获取 mapper 接口
        List<User> userList = sqlSession.selectList("com.hkp.mapper.UserMapper.getUser",null, rowBounds);
    
        // 关闭会话,释放资源
        sqlSession.close();
    
        //打印结果
        for (User user2 : userList) {
            System.out.println(user2);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    使用注解开发CRUD

    映射的语句可以不用 XML 来配置,而可以使用 Java 注解来配置。比如,上面的 XML 示例可以被替换成如下的配置:

    package org.mybatis.example;
    public interface BlogMapper {
      @Select("SELECT * FROM blog WHERE id = #{id}")
      Blog selectBlog(int id);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    使用注解来映射简单语句会使代码显得更加简洁,但对于稍微复杂一点的语句,Java 注解不仅力不从心,还会让你本就复杂的 SQL 语句更加混乱不堪。 因此,如果你需要做一些很复杂的操作,最好用 XML 来映射语句。

    核心配置文件

    
    DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    
    <configuration>
        
        <properties resource="db.properties">properties>
    
        
        <settings>
            
            <setting name="logImpl" value="LOG4J" />
        settings>
        <typeAliases>
            <package name="com.hkp.entity"/>
        typeAliases>
        
        <environments default="development">
            <environment id="development">
                
                <transactionManager type="JDBC" />
                
                <dataSource type="POOLED">
                    
                    <property name="driver" value="${driver}" />
                    
                    <property name="url" value="${url}" />
                    
                    <property name="username" value="${user}" />
                    
                    <property name="password" value="${password}" />
                dataSource>
            environment>
        environments>
    
        
        <mappers>
            <mapper class="com.hkp.mapper.UserMapper"/>
        mappers>
    configuration>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    查询

    接口

    package com.hkp.mapper;
    
    import com.hkp.entity.User;
    import org.apache.ibatis.annotations.Select;
    import java.util.List;
    
    public interface UserMapper {
       @Select("select * from smbms_user")
       List<User> getUser();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    测试

    @Test
    public void test() {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        // 获取 mapper 接口
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> user = mapper.getUser();
    
        // 关闭会话,释放资源
        sqlSession.close();
    
        //打印结果
        for (User user2 : user) {
            System.out.println(user2);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    增加

    接口

    package com.hkp.mapper;
    
    import com.hkp.entity.User;
    import org.apache.ibatis.annotations.Insert;
    import java.util.List;
    
    public interface UserMapper {
       @Insert("INSERT INTO `smbms`.`smbms_user` ( `userName`, `userPassword`, `address` ) VALUES(#{userName},#{userPassword},#{address});")
       int addUser(User user);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    测试

    @Test
    public void test() {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        // 获取 mapper 接口
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        // 获取接口中的方法
        User u=new User();
        u.setUserName("测试");
        u.setUserPassword("test");
        u.setAddress("测试");
        int count = userMapper.addUser(u);
        //增删改 影响数据库的操作需要做提交操作
        sqlSession.commit();
        // 关闭会话,释放资源
        sqlSession.close();
        // 查询到的数据
        System.out.println("影响数据库行数 :"+count);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    删除

    接口

    package com.hkp.mapper;
    
    import com.hkp.entity.User;
    import org.apache.ibatis.annotations.Delete;
    import java.util.List;
    
    public interface UserMapper {
       @Delete("DELETE FROM smbms_user WHERE id=#{id}")
       int deleteUser(@Param("id") int id);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    测试

    @Test
    public void test() {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        // 获取 mapper 接口
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        // 获取接口中的方法
        int count = userMapper.deleteUser(24);
        //增删改 影响数据库的操作需要做提交操作
        sqlSession.commit();
        // 关闭会话,释放资源
        sqlSession.close();
        // 查询到的数据
        System.out.println("影响数据库行数 :"+count);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    修改

    接口

    package com.hkp.mapper;
    
    import com.hkp.entity.User;
    import org.apache.ibatis.annotations.Update;
    import java.util.List;
    
    public interface UserMapper {
       @Update("UPDATE `smbms`.`smbms_user` \n" +
               "\t\tSET `userName` = #{userName},\n" +
               "\t\t`userPassword` = #{userPassword},\n" +
               "\t\t`address` = #{address}\n" +
               "\t\tWHERE\n" +
               "\t\t\t`id` = #{id};")
       int updateUser(User user);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    测试

    @Test
    public void test() {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        // 获取 mapper 接口
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        // 获取接口中的方法
        User u=new User();
        u.setId(16);
        u.setUserName("测试udpate");
        u.setUserPassword("test");
        u.setAddress("测试");
        int count = userMapper.updateUser(u);
        //增删改 影响数据库的操作需要做提交操作
        sqlSession.commit();
        // 关闭会话,释放资源
        sqlSession.close();
        // 查询到的数据
        System.out.println("影响数据库行数 :"+count);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    关于 @Param(“”) 注解

    • 基本类型和String 类型都要加上该注解
    • 包装类不需要加这个注解
    • 如果只有一个参数,而且参数类型为基本类型或String类型,可以忽略不加该注解,但是建议加上

    ${} 和 #{}

    #{} 安全,可以防止 SQL 注入

    ${} 不安全

  • 相关阅读:
    RHCE 9.0培训课程之容器技术的运行
    Vue---SCSS
    [centos]centos7源码编译cmake报错Could NOT find OpenSSL
    通关GO语言04 集合类型:如何正确使用 array、lice 和 map?
    微服务从代码到k8s部署应有尽有系列(八、各种队列)
    conda和Python的虚拟环境如何结合使用,以及二者之间到底有什么区别?
    大厂密集背后,折叠屏市场“暗战”已起
    WMS供应商管理功能SupplierService
    Linux: network: demux 解释
    DeepStream--测试TrafficCamNet检测模型
  • 原文地址:https://blog.csdn.net/weixin_46047612/article/details/126134320