• Mybatis详解


    Mybatis

    1.Mybatis概述

    1.1什么Mybatis?
    • Mybatis原本是apache的一个开源项目(当时叫iBatis), 2010年6月这个项目由ApacheSoftware Foundation 迁移到了 Google Code,随着开发团队转投GoogleCode 旗下, iBatis3.x正式更名为MyBatis。

    • Mybatis是一款优秀的持久性框架

    • Mybatis几乎避免了所有的手动jdbc设置以及手动获得结果集的操作。

    • 它是一款半自动的ORM持久层框架,具有较高的SQL灵活性,支持高级映射(一对一,一对多),动态SQL,延迟加载和缓存等特性。

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

    • Mybatis支持动态sql以及数据缓存。

      Mybatis 中文官网 https://mybatis.org/mybatis-3/zh/getting-started.html

    1.2什么是ORM?

    Object Relation Mapping,对象关系映射。对象指的是Java对象,关系指的是数据库中的关系模型,对象关系映射,指的就是在Java对象和数据库的关系模型之间建立一种对应关系,比如用一个Java的Student实体类,去对应数据库中的一张student表,类中的属性和表中的列一一对应()。Student类就对应student表,一个Student对象就对应student表中的一行数据。

    2.Mybatis环境搭建

    2.1建立对象关系映射(ORM)

    在idea中建立一个与数据库表对应的实体类。

    2.2导入Mybatis jar包和sql数据库驱动包
    //配置mysql
    
    <dependency>
        <groupId>mysqlgroupId>
        <artifactId>mysql-connector-javaartifactId>
        <version>8.0.16version>
    dependency>
    
    //配置mybatis
    <dependency>
                <groupId>org.mybatisgroupId>
                <artifactId>mybatisartifactId>
                <version>3.4.2version>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    2.3建立Mybatis全局配置文件
    
    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">
    <dataSource type="POOLED">
    <property name="driver" value="" />
    <property name="url" value="" />
    <property name="username" value="" />
    <property name="password" value=""/>
    dataSource>
    environment>
    environments>
    configuration>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    2.4建立sql映射文件
    
    DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="接口地址">
    定义 sql 语句
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    2.5定义接口并在接口中配置方法进行数据处理

    3测试Mybatis

    1.读取配置文件
    Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
    
    • 1
    2.创建 SqlSessionFactory
    SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
    
    • 1

    SqlSessionFactory是Mybatis的关键对象,SqlSessionFactory单个数据映射关系经过编译后的内存镜像,SqlSessionFactory实例由SqlSessionFactoryBuilder对象获得,Mybatis以SqlSessionFactory为核心,并且SqlSessionFactory是线程安全的,SqlSessionFactory一旦被创建,在整个的执行过程中都是存在的,在运行期间不建议多次创建,建议使用单例模式:

    	package com.ffyc.mybatisdemo.util;
    
    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 {
    
    	static SqlSessionFactory sqlSessionFactory =null;
    
    	//当MybatisUtil类第一次加载时,静态代码块执行,创建SqlSessionFactory
    	static{
    		//读取全局配置文件
    		InputStream inputStream = null;
    		try {
    			inputStream = Resources.getResourceAsStream("mybatisConfig.xml");
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    
    		//创建sqlSessionFactory,由sqlSessionFactory构建sqlsession
    		//由于创建sqlSessionFactory开销较大,用于封装数据库的连接信息,所以没有必要每次都创建
    		sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    	}
    	//获得通过静态代码块建立的创建sqlSessionFactory来建立sqlsession
    	public static SqlSession getSqlSession(){
    		return sqlSessionFactory.openSession();
    	}
    }
    
    • 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
    3.建立SqlSession
    SqlSession sqlSession = sessionFactory.openSession()
    
    • 1

    SqlSession是MyBatis实现数据持久化的关键对象,类似于JDBC的connection,SqlSession是应用层与持久层之间执行交互操作的一个单线程对象.每个线程都应该有它自己的SqlSession实例.SqlSession的实例不能被共享,同时SqlSession也是线程不安全的,绝对不能讲SqlSeesion实例的引用放在一个类的静态字段甚至是实例字段中.也绝不能将SqlSession实例的引用放在任何类型的管理范围中,在该线程执行(与数据库会话结束后)完后必须关SqlSession。

    4.获得接口代理对象
    sqlSession.getMapper(接口.class)
    
    • 1

    动态为接口创建一个代理对象,由Mybatis框架自动生成,由代理对象调用Mapper中的方法;

    5.API接口说明
    • SqlSessionFactory 接口
      使用 SqlSessionFactory 来创建 SqlSession,一旦创建 SqlSessionFactory 就会在整个应用过程中始终存在。由于创建开销较大,所以没有理由去销毁再创建它,一个应用运行中也不建议多次创建 SqlSessionFactory。
    • SqlSession 接口
      Sqlsession 意味着创建与数据库链接会话,该接口中封装了对数据库操作的方法,与数据库会话完成后关闭会话。
    • Mybatis-Dao 层 Mapper 接口化开发
      Mapper 接口开发方式只需要程序员编写 Mapper 接口,由 Mybatis 框架创建接口的动态代理对象,使用 sqlsession.getMapper(接口.class);获得代理对象. Mapper 接口开发需要遵循以下规范:
      • 1、 Mapper.xml 文件中的 namespace 与 mapper 接口的类路径相同.
      • 2、 Mapper 接口方法名和 Mapper.xml 中定义的每个 statement 的 id 相同.
      • 3、 Mapper 接口方法的输入参数类型和 mapper.xml 中定义的每个 sql 的parameterType 的类型相同.
      • 4、 Mapper 接口方法的输出参数类型和 mapper.xml 中定义的每个 sql 的resultType 的类型相同
    6.Mybatis日志

    具体选择哪个日志实现由 MyBatis 的内置日志工厂确定。它会使用最先找到的。Mybatis 内置的日志工厂提供日志功能,具体的日志实现有以下几种方式:

    <settings>
    <setting name="logImpl" value="STDOUT_LOGGING"/>
    settings>
    
    • 1
    • 2
    • 3
    7.建立一个Dao类(进行数据操作
    package com.ffyc.mybatisdemo.dao;
    
    import com.ffyc.mybatisdemo.model.Admin;
    
    import org.apache.ibatis.annotations.Param;
    
    import java.util.List;
    
    public interface AdminDao {
    	//方法名与对应的mapper中的标签id相同,
    	//方法的参数值,返回值类型要与mapper中的标签中定义的参数值和返回类型相同
    	Admin findAdminById(int id);
    
    	Admin login(@Param("account") String account, @Param("password") String password);
    
    	Admin login2(Admin admin);
    
    	int saveAdmin(Admin admin);
    
    	int updateAdmin(Admin admin);
    
    	int deleteAdmin(Admin admin);
    
    	Admin findAdminById1(int id);
    
    
    	Admin findAdminById2(int id);
    
    
    	int findAdminCount();
    
    	List<Admin> findAdminList();
    
    }
    
    • 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
    8.建立一个Mappers映射文件(编写SQL)
    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    
    <mapper namespace="com.ffyc.mybatisdemo.dao.AdminDao">
        <update id="updateAdmin" parameterType="Admin">
            update admin set account=#{account}, password=#{password},gender=#{gender} where id=#{id}
        update>
    
    
        <delete id="deleteAdmin">
            delete from admin where id=#{id}
        delete>
    
    
        <select id="findAdminById" parameterType="int" resultType="Admin">
            select * from admin where id = #{id}
      select>
    
    
        <select id="login" resultType="Admin">
            select*from admin where account=#{account} and password=#{password}
        select>
    
    
        <select id="login2" parameterType="Admin" resultType="Admin">
            select*from admin where account=#{account} and password=#{password}
        select>
    
    
        
        <select id="findAdminById1" parameterType="int" resultType="Admin">
            select account,password,gender xb from admin where id=#{id}
        select>
    
        
        <select id="findAdminCount" parameterType="int" resultType="java.lang.Integer">
            select count(*) from admin
        select>
    
    
        
        <resultMap id="adminMap" type="admin">
            <result column="gender" property="xb">result>
        resultMap>
        <select id="findAdminById2" parameterType="int" resultMap="adminMap">
            select * from admin where id = #{id}
        select>
    
        
        <resultMap id="adminListMap" type="admin">
            <result column="gender" property="xb">result>
        resultMap>
        <select id="findAdminList" resultMap="adminListMap">
            select * from admin
        select>
    
    
        
        <insert id="saveAdmin" parameterType="Admin" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
            insert into admin(account,password,gender)values(#{account},#{password},#{gender})
        insert>
    
    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
    • 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
    9.编辑数据源properties文件
    driverName=com.mysql.cj.jdbc.Driver
    url=jdbc:mysql://127.0.0.1:3306/ssmdb?serverTimezone=Asia/Shanghai
    username=root
    password=root
    
    • 1
    • 2
    • 3
    • 4
    10.编辑全局配置文件
    
    DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
    
    
        
        <properties resource="config.properties">properties>
        
        
        <settings>
            <setting name="logImpl" value="STDOUT_LOGGING"/>
            <setting name="mapUnderscoreToCamelCase" value="true"/>
        settings>
        
        <typeAliases>
        
            <package name="com.ffyc.mybatisdemo.model"/>
        typeAliases>
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <property name="driver" value="${driverName}"/>
                    <property name="url" value="${url}"/>
                    <property name="username" value="${username}"/>
                    <property name="password" value="${password}"/>
                dataSource>
            environment>
        environments>
        <mappers>
            <mapper resource="mappers/AdminMapper.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
    11.测试(利用Test标签测试)
    package com.ffyc.mybatisdemo.test;
    
    import com.ffyc.mybatisdemo.dao.AdminDao;
    import com.ffyc.mybatisdemo.model.Admin;
    import com.ffyc.mybatisdemo.util.MyBatisUtil;
    
    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    
    public class Test2 {
    	@Test
    	public void login() {
    		SqlSession sqlSession = MyBatisUtil.getSqlSession();
    		AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
    		adminDao.login("admin1","111");
    		sqlSession.close();
    	}
    	@Test
    	public void login2() {
    		SqlSession sqlSession = MyBatisUtil.getSqlSession();
    		AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
    		Admin admin = new Admin("admin1","111","男");
    		adminDao.login2(admin);
    		sqlSession.close();
    	}
    	@Test
    	public void save() {
    		SqlSession sqlSession = MyBatisUtil.getSqlSession();
    		AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
    		Admin admin = new Admin("admin2","222","女");
    		adminDao.saveAdmin(admin);
    		sqlSession.commit();
    		sqlSession.close();
    	}
    	@Test
    	public void update() {
    		SqlSession sqlSession = MyBatisUtil.getSqlSession();
    		AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
    		Admin admin = new Admin("admin5","555","男");
    		admin.setId(2);
    		adminDao.updateAdmin(admin);
    		sqlSession.commit();
    		sqlSession.close();
    	}
    
    
    	@Test
    	public void delete() {
    		SqlSession sqlSession = MyBatisUtil.getSqlSession();
    		AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
    		Admin admin = new Admin("admin5","555","男");
    		admin.setId(2);
    		adminDao.deleteAdmin(admin);
    		sqlSession.commit();
    		sqlSession.close();
    	}
    }
    
    
    • 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

    在这里插入图片描述

    12.总结
    • 编写mapper.xml,书写SQL,并定义好SQL的输入参数,和输出参数

    • 编写全局配置文件,配置数据源,以及要加载的mapper.xml文件

    • 通过全局配置文件,创建SqlSessionFactory

    • 每次进行CRUD时,通过SqlSessionFactory创建一个SqlSession

    • 调用SqlSession上的selectOne,selectList,insert,delete,update等方法,传入mapper.xml中SQL标签的id,以及输入参数

    • 注意:全局配置文件中,各个标签要按照如下顺序进行配置,因为mybatis加载配置文件的源码中是按照这个顺序进行解析的,每有新建并要使用的mapper.xml文件一定要在mappers中进行配置。

      <configuration>
      	
           properties  
           settings	
      
           typeAliases
          <typeAliases>
              <package name="com.ffyc.mybatisdemo.model"/>
          typeAliases>
      
          
           mappers
           -->
      configuration>
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15

    4.Mappers与Dao

    在使用Dao类中的接口与Mappers.xml文件进行绑定时要注意:

    • mapper中命名空间必须唯一(必须指向该Dao类)

      <mapper namespace="com.ffyc.mybatisdemo.dao.AdminDao">
      
      • 1
    • 使用接口与xml进行绑定时 接口方法要与mapper.xml中id保持一致

      int updateAdmin(Admin admin);
      
      • 1
          <update id="updateAdmin" parameterType="Admin">
              update admin set account=#{account}, password=#{password},gender=#{gender} where id=#{id}
          update>
      
      • 1
      • 2
      • 3
    • Dao接口方法的入参,出参类型与mapper.xml标签中定义的参数值和返回类型相同

      int updateAdmin(Admin admin);
      
      • 1
       parameterType="Admin"
      
      • 1

    5.注解

    注解在没有嵌套查询的情况下,是很便捷的,但是使用注解会让SQL语句注入到运行代码中,若是要修改SQL语句就要去修改代码,可维护性不强。

    在使用注解时不需要使用mapper.xml文件去进行数据处理,之间在Dao中编写SQL语句对数据进行操作。

    常见的操作(增,删,改,查)如下:

    	@Insert("insert into grade(name) value(#{name}) ")
    	 int saveGrade(Grade grade);
    	@Delete("delete from grade where id=#{id}")
    	int deleteGrade(int id);
    	@Update("update grade set name=#{name} where id=#{id}")
    	int updateGrade(Grade grade);
    	@Select("select * from grade where id=#{id}")
    	Grade findGradeById(int id);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    6.主键设置

    当我们在数据库中进行插入操作时,数据库的主键通常会自增,而我们要如何得到在数据库中生成的新主键?

    使用 useGeneratedKeys=“true” 支持取出数据库生成的主键 和 keyColumn=“id” 指定主键列

        
        <insert id="saveAdmin" parameterType="Admin" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
            insert into admin(account,password,gender)values(#{account},#{password},#{gender})
        insert>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    7.批量查询

    主要是动态SQL标签的使用,注意如果入参类型parameterTypeList的话,则在标签体内引用这个List,只能用变量名list,如果parameterType是数组,则只能用变量名array

        <select id="findStudentList1" resultType="Student" parameterType="List">
            select * from student where no in
            <foreach collection="list" open="(" item="no" separator="," close=")">
                #{no}
            foreach>
        select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    Dao:

    List<Student> findStudentList1(List<Integer> list);
    
    • 1

    Test:

    	@Test
    	public void findStudentList(){
    		SqlSession sqlSession = MyBatisUtil.getSqlSession();
    		StudentDao1 studentDao1 = sqlSession.getMapper(StudentDao1.class);
    		List<Integer> list = new ArrayList<>();
    		list.add(111);
    		list.add(222);
    		studentDao1.findStudentList1(list);
    		sqlSession.close();
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    结果:

    在这里插入图片描述

    8.动态Sql

    在mapper中使用sql语句并要对查询的数据进行筛选等操作,我们就要利用动态Sql。

    在没有使用MYbatis之前,我们对于该类语句是如何处理的?

    Class.forName("com.mysql.cj.jdbc.Driver");
    			connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/smartschool?serverTimezone=Asia/Shanghai", "root", "root");
    			String sql="SELECT \n" +
    					"d.id,\n" +
    					"d.dorm_num,\n" +
    					"d.num dnum,\n" +//人数
    					"d.floor_num,\n" +
    					"d.state,\n" +
    					"b.name bname,\n" +
    					"da.name daname,\n" +
    					"b.num bnum,\n" +//楼层数
    					"a.account,\n" +
    					"d.oper_time\n" +
    					"FROM dorm d LEFT JOIN building b ON d.buildingid= b.id\n" +
    					"LEFT JOIN admin a ON d.admin = a.id " +
    					"LEFT JOIN dorm_admin da ON b.dorm_adminid=da.id" +
    					" where 1=1";
    			if(dorm_num!=null&&dorm_num!=""){
    				sql+=" and d.dorm_num='"+dorm_num+"'";
    			}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    由上述代码可以看出,我们在之前想要对查询的数据进行比对,筛选时为了避免Sql异常通常选择在sql语句的末端拼上where 1=1

    而在引入动态Sql后完全可以避免此类语句的注入。

    Mybatis中的动态标签:

    where if

    select * from student
            <where>
                <if test="name!=null&name!=''">
                    name=#{name}
                if>
                <if test="no!=null&no!=''">
                    and no=#{no}
                if>
            where>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    一旦where标签中有if条件成立会自动生成where,否则不生成若是第一位if条件不成立,而第二位if成立,则if语句中的and会自动被(mybatis)去除
    
    • 1

    tirm

      select * from student
      <trim prefix="where" prefixOverrides="and|or"> /*可添加前缀或覆盖多余字段*/
                <choose>
                    <when test="name!=null">
                        name=#{name}
                    when>
                    <otherwise>
                        name="李四"
                    otherwise>
                choose>
            trim>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    trim prefix="自定义前缀" prefixOverrides="覆盖指定的关键字
    
    • 1

    choose when otherwise

            <trim prefix="where" prefixOverrides="and|or"> /*可添加前缀或覆盖多余字段*/
                <choose>
                    <when test="name!=null">
                        name=#{name}
                    when>
                    <otherwise>
                        name="李四"
                    otherwise>
                choose>
            trim>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    choose 分支执行when test="条件" 成立执行 否则 otherwise
    
    • 1

    set

        <update id="updateStudent">
            update student
            <set>
                <if test="name!=null">
                    name=#{name},
                if>
                <if test="gender!=null">
                    gender=#{gender}
                if>
            set>
            where id=#{id}
        update>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    在至少有一个子元素返回了SQL语句时,才会向SQL语句中添加SET,并且如果SET之后是以`,`开头的话,会自动将其删掉
    
    • 1

    foreach

     <select id="findStudentList1" resultType="Student" parameterType="List">
            select * from student where no in
            <foreach collection="list" open="(" item="no" separator="," close=")">
                #{no}
            foreach>
        select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    用来做迭代拼接的,通常会与SQL语句中的IN查询条件结合使用,注意,到parameterType为List(链表)或者Array(数组),后面在引用时,参数名必须为list或者array。如在foreach标签中,collection属性则为需要迭代的集合,由于入参是个List,所以参数名必须为list
    
    • 1

    sql

        <sql id="selectStudent">
                SELECT
                  s.id,
                  s.name sname,
                  s.gender,
                  s.no,
                  a.account,
                  g.name gname
                FROM
                  student s
                  LEFT JOIN admin a
                    ON s.adminid = a.id
                  LEFT JOIN grade g
                    ON s.gradeid = g.id
        sql>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
        <select id="findStudentList" resultMap="studentMap">
            <include refid="selectStudent">include>
        select>
    
    • 1
    • 2
    • 3
    可将重复的SQL片段提取出来,然后在需要的地方,使用``标签进行引用
    
    • 1

    9.关联查询

    嵌套查询通常使用在一个实体类中包含另一个类,若这个被包含的类在该类中的形式是集合或数组则在mapper中使用嵌套查询时要使用collection标签否则使用association

    使用这个嵌套查询,需要注意的是collection和association有如下属性

    • property 实体中对应的属性,这里是depts。
    • javaType 实体属性的类型,这里是一个集合,所以使用java.util.ArrayList表示。
    • ofType 集合范型中的类型,这里是部门信息,对应java类Department
    • select 嵌套子查询的ID
    • column 这里最关键,也比较难理解,默认一个参数,可以直接写column = “id”,最后根据参数类型匹配。这里其实是传入子查询中的参数,也就是子查询的关联属性user_id对应的参数值,在collection这里就是主sql中查询出来的列值,如果这里id有了别名,比如emp_id,这里就应该写column = “emp_id”。还有一种写法,通过大括号来表示,这种写法可以传入多个参数(多个参数用逗号隔开)。对于本示例而言,正确的写法就是column={userId=id},userId对应 queryByUserId查询语句中 SELECT * FROM xx_dept WHERE user_id = #{userId} 参数userId。id就是主sql查询出来的列id值,就是xx_emp对应的id列值。
        <resultMap id="GradeMap1" type="grade">
            <id column="id" property="id">id>
            <result column="name" property="name">result>
            <collection property="students" javaType="list" ofType="Student" column="id" select="findStudentByGradeId">collection>
        resultMap>
        <select id="findGradeList1" resultMap="GradeMap1">
                SELECT
                  id,
                  name
                FROM
                  grade
        select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    10.缓存

    一级缓存

    默认开启,同一个SqlSesion级别共享的缓存,在一个SqlSession的生命周期内,执行2次相同的SQL查询,则第二次SQL查询会直接取缓存的数据,而不走数据库,当然,若第一次和第二次相同的SQL查询之间,执行了DML(INSERT/UPDATE/DELETE),则一级缓存会被清空,第二次查询相同SQL仍然会走数据库。

    一级缓存在下面情况会被清除

    在同一个SqlSession下执行增删改操作时(不必提交),会清除一级缓存
    SqlSession提交或关闭时(关闭时会自动提交),会清除一级缓存
    对mapper.xml中的某个CRUD标签,设置属性flushCache=true,这样会导致该MappedStatement的一级缓存,二级缓存都失效(一个CRUD标签在mybatis中会被封装成一个MappedStatement)
    在全局配置文件中设置 ,这样会使一级缓存失效,二级缓存不受影响

    二级缓存

    默认关闭,可通过全局配置文件中的开启二级缓存总开关,然后在某个具体的mapper.xml中增加,即开启了该mapper.xml的二级缓存。二级缓存是mapper级别的缓存,粒度比一级缓存大,多个SqlSession可以共享同一个mapper的二级缓存。注意开启二级缓存后,SqlSession需要提交,查询的数据才会被刷新到二级缓存当中

  • 相关阅读:
    Mysql 和 Redis 数据如何保持一致
    mybatis实现插入数据时获取主键
    Vue系列之Vue实例化
    MAC地址震荡,STP震荡,OSPF路由协议震荡
    删库遭 GitHub 封号,开发者欲夺回发行权:“我只是犯了个编程错误”
    如何为勒索软件攻击做准备?
    面试题-React(九):React的Context:实现非父子组件通信
    Pytorch 常用函数
    openEuler(arm架构)系统中mysql8.x安装问题解决
    Redis集群搭建
  • 原文地址:https://blog.csdn.net/weixin_52340450/article/details/125816274