Mybatis学习笔记

参考文档:https://mybatis.org/mybatis-3/zh/

什么是Mybatis

非常简单地讲,
Mybatis是一种持久层框架,
Mybatis支持对象关系映射,即一个类对应一张表。

持久层: 具有将将数据持久化功能的层,即将瞬时的数据保存到数据库或是硬盘中,使其能长期保存

对象关系映射:即Mapper,通过一个Mapper接口对应一张表,通过xml文件指定该接口来实现数据库的操作

使用Mybatis简单步骤

1. 新建

a. 新建一个空Maven项目,删除src目录添加模块
b. 新建文件夹及文件,具体如图在这里插入图片描述

2. 基础的配置和类的写法

mybatis-config.xml是Mybatis的配置文件,配置如下

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<!-- 环境,可以配置多套,在default中选择使用环境的id切换 -->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
            	<!-- 加载驱动,value为驱动类名(根据实际填写) -->
                <property name="driver" value="com.mysql.cj.jdbc.Driver" />
                <!--  数据库位置及连接参数配置,&amp;是&的转义 -->
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&amp;characterEncoding=UTF-8&amp;userSSL=true&amp;serverTimezone=GMT%2B8" />
                <!-- 数据库用户名及密码 -->
                <property name="username" value="root" />
                <property name="password" value="112159" />
            </dataSource>
        </environment>
    </environments>
	<!-- 映射文件位置,写全包名 -->
    <mappers>	
        <mapper resource="com/hoppi/mapper/UserMapper.xml" />
    </mappers>
</configuration>

需按次序写标签
在这里插入图片描述

MybatisUtil是Mybatis的工具类,调用其中方法得到一个SqlSession对象,示例如下

package com.hoppi.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 {
        try {
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public static SqlSession getSqlSession() {
        return sqlSessionFactory.openSession();
    }
}

User是实体类,即和表对应的类,具有表中字段对应的属性和Getter/Setter方法以及toString方法(可有可无吧),示例如下

package com.hoppi.pojo;

public class User {
	//属性
    private int id;
    private String name;
    private String password;
	//无参构造
    public User() {
    }
	//有参构造
    public User(int id, String name, String password) {
        this.id = id;
        this.name = name;
        this.password = password;
    }
	//Getter/Setter
    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
	//toString
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

想偷懒的话可以导入Lombok包(或添加Maven依赖),为这个类加@Data@AllArgsConstructor(有参构造)、@NoArgsConstructor(无参构造)注释,如果有父类再加个@EqualsAndHashCode(callSuper = true),这样只要写属性就行了
值得注意的是Lombok写pojo这种大量的简单的重复的类时用用就行了,这玩意缺陷很多,争议也很多,可以参考这篇文章:Lombok的优劣势

UserMapper是User类对应的映射接口(注意是接口),其中有数据库增删改查等方法声明,示例如下

package com.hoppi.mapper;

import com.hoppi.pojo.User;

import java.util.List;

public interface UserMapper {
	//打印user表
    List<User> getUserList();
    
    User getUserById(int id);
    int insert(User user);
}

UserMapper.xml则是UserMapper接口对应配置文件,其中包括接口映射和各种JDBC(如select)元素,接口映射的命名空间用于声明该文件对应的接口,配置如下

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- 映射接口相对路径 -->
<mapper namespace="com.hoppi.mapper.UserMapper">
	<!-- id为对应接口中的方法名 resultType(resultMap)为返回类型 -->
    <select id="getUserList" resultType="com.hoppi.pojo.User">
        select * from mybatis.users
    </select>
    <!-- parameterType为传入参数类型 #{}类似占位符,其中的内容为对应方法传入参数名 -->
    <select id="getUserById" parameterType="int" resultType="com.hoppi.pojo.User">
        select * from mybatis.users where id = #{id}
    </select>
    <!--  -->
    <insert id="insert" parameterType="com.hoppi.pojo.User">
        insert into mybatis.users(id,name,password) values (#{id},#{name},#{password})
    </insert>
</mapper>

3. 快进到使用

第一步,获得SqlSession对象

//工具类静态方法getSqlSession得到SqlSession对象
SqlSession sqlSession = MybatisUtil.getSqlSession();

第二步,获得Mapper对象

//这里获得UserMapper对象
UserMapper mapper = sqlSession.getMapper(UserMapper.class);

第三步,使用Mapper中的方法

注意:增删改需要提交事务,即sqlSession.commit();
如果不想手动提交,可以在Mybatis工具类中给openSession()方法传递一个true

第四步,关闭SqlSession

sqlSession.close();

稍微高级一点的写法

1. Map

当表的字段过多而我们不希望修改一条记录中所有字段,或插入时不希望插入有默认值或可为空的字段,以及多条件查询时,我们可以使用Map类型传参,当然,其他的操作想的话也可以这么用,但是一般还是用实体类
至于为什么用Map,因为Mybatis只能传递一个参数

示例如下

//来一个新的insert方法
int insert2(Map<String, Object> map);
<!-- xml中配置, user_id、user_name、user_password为传入Map中的key -->
<insert id="insert2" parameterType="map">
   insert into mybatis.users(id,name,password) values (#{user_id},#{user_name},#{user_password})
</insert>
//来个测试方法
@org.junit.Test
   public void test() {
       SqlSession sqlSession = MybatisUtil.getSqlSession();
       UserMapper mapper = sqlSession.getMapper(UserMapper.class);
       
       for (User user : mapper.getUserList()) {
           System.out.println(user);
       }
       //关键操作
       Map<String, Object> map = new HashMap<>();
       map.put("user_id", "10000005");
       map.put("user_name", "狗子");
       map.put("user_password", "1919810");
       
       mapper.insert2(map);
       
       sqlSession.commit();
       
       for (User user : mapper.getUserList()) {
           System.out.println(user);
       }
       
       sqlSession.close();
   }

2. 外部配置文件

可以在Mybatis配置文件中引入配置文件

第一步·新建配置文件,例如
在这里插入图片描述
第二步·写入参数

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=UTF-8&userSSL=true&serverTimezone=GMT%2B8
username=root
password=112159

第三步·在mybatis-config.xml中指定配置文件并传参

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<!-- 指定配置文件 -->
    <properties resource="db.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="${username}" />
                <property name="password" value="${password}" />
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="com/hoppi/mapper/UserMapper.xml" />
    </mappers>
</configuration>

非常特殊的一点,<properties>标签内可以用<property name="xxx" value="xxx" />标签来传入键值对,在<dataSource>中依然可以通过name取出这些value使用,但当与外部配置文件中内容冲突时优先级低于配置文件
另外,如果出现找不到资源文件的问题,在该项目的pom.xml中配置<build>-><resources>-><resource>标签,添加

   <directory>资源文件所在目录如src/main/resources</directory>
   <includes>
       <!-- 根据自己需要配置需导入的文件类型 -->
       <include>**/*.xml</include>
       <include>**/*.properties</include>
   </includes>
   <filtering>true</filtering>

3. 类型别名

类型别名用于在mapper.xml中消除冗余,比如说在我UserMapper.xml文件中写一个User类用的是包含其路径的,即com.hoppi.pojo.User,我们想要使用它的缩写或类名来代替全名,故产生了这种功能

具体的用法是在Mybatis配置文件的<typeAliases>下加入<typeAlias type="具体类名" alias="简称"/><typeAlias type="com.hoppi.pojo.User" alias="User"/>以简称代替全称 加入<package name="类所在包名如com.hoppi.pojo"/>指定包名以允许不使用全称,第二种方式的默认别名为该包下实体类的名称,首字母大小写皆可,但推荐使用小写以区分类型,想自定义别名可以在该类添加注解@Alias("xxx"),但弹幕君建议大家最好不要用注解,弹幕有云,注解一时爽,维护火葬场

4. 结果集映射

解决的问题:实体类属性名与对应表字段名不一致
通常用于复杂的sql查询

较为普通的操作是,当实体类属性与表字段名不同且在写Mapper.xml的查询操作需要返回实体类对象时,例如我将User实体类中password属性改名为pwd,再去使用getUserList时。
将返回结果resultType="实体类名"改为resultMap=“Map名”,并编写Map中的映射,例如

<select id="getUserList" resultType="user">
    select * from mybatis.users
</select>

—>

<resultMap id="userMap" type="user">
    <!-- 只需要编写属性字段名不同的映射 -->
    <result column="password" property="pwd"/>
</resultMap>
<select id="getUserList" resultMap="userMap">
    select * from mybatis.users
</select>

5. 日志输出

a. 标准日志输出
在mybatis-config.xml中配置setting的logImplSTDOUT_LOGGING,如图:在这里插入图片描述
这样执行的时候就会标准化打印日志了

b. Log4j
配置setting的logImplLog4j
为该项目导入Apache Log4j 1.2的包或是添加Maven依赖
当然是选择添加依赖啦
在Maven Repository中找到这个包的依赖

<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

在pom.xml中添加
之后在resources目录下新建log4j.xml(以前是.properties,现在建议用xml),内容自行百度或CSDNlog4j.xml通用配置
直接复制使用(毕竟小白谁愿意去研究一眼看上去一团屎的东西呢)
参考这篇文章:Log4J.xml配置详解
但是现在能找到的配置都挺老的,这里贴一份修改过的到2021.08.08还能用的配置

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/doc-files/log4j.dtd">

<log4j:configuration debug="true">
    <appender name="myConsole" class="org.apache.log4j.ConsoleAppender">
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern"
                   value="[%d{dd HH:mm:ss,SSS\} %-5p] [%t] %c{2\} - %m%n"/>
        </layout>
        <!--过滤器设置输出的级别-->
        <filter class="org.apache.log4j.varia.LevelRangeFilter">
            <param name="levelMin" value="debug"/>
            <param name="levelMax" value="warn"/>
            <param name="AcceptOnMatch" value="true"/>
        </filter>
    </appender>
    <appender name="myFile" class="org.apache.log4j.RollingFileAppender">
        <!-- 设置日志输出文件名,./代表项目目录 -->
        <param name="File" value="./output/output.log"/>
        <!-- 设置是否在重新启动服务时,在原有日志的基础添加新日志 -->
        <param name="Append" value="false"/>
        <param name="MaxBackupIndex" value="10"/>
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%p (%c:%L)- %m%n"/>
        </layout>
    </appender>
    <!-- 根logger的设置-->
    <root>
        <priority value="debug"/>
        <appender-ref ref="myConsole"/>
        <appender-ref ref="myFile"/>
    </root>
</log4j:configuration>

在需要输出日志的类中加上

static Logger logger = Logger.getLogger(这个类的类名.class);

注意这里导入的包是org.apache.log4j.Logger
然后可以在此类的方法中通过logger对象输出日志,比如logger.info("提示语")logger.debug("提示语")logger.error("提示语"),个人习惯把"提示语"换成this,这样可以打印相对路径
当然,只要在mybatis-config.xml中有配置log4j日志输出并且正确配置都会输出日志(部分),注意当取消日志输出的时候要记得删掉或注释掉pom.xml中的log4j依赖,否则会出现报错

log4j:WARN No appenders could be found for logger (org.apache.ibatis.logging.LogFactory).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.

注解代替xml

首先明确一点,注解与xml配置不能同时作用于同一方法
再然后注解主要用于简单的sql语句,对于复杂的sql推荐使用xml配置
注解与xml的语法一模一样,但如果传入的基本类型参数有多个(它可以做到直接传入多个参数而不使用Map),必须在参数前加@Param("映射名")注释,而引用类型没有说明强制使用,映射名是被sql语句中的#{}调用的名字

举个例子

@Update("update mybatis.users set name=#{name},password=#{password} where id=#{id}")
    void update(@Param("id") int user_id, @Param("name") String user_name, @Param("password") String password);

记录一个离谱的关于中文乱码的问题,我到这一步传入中文name都是乱码,所有配置都是正确的,百度CSDN博客园根本查不到,直接气死,后来直接复制一下这个模块的内容到一个新建的模块中,这个bug魔幻地被解决了,初步猜想和缓存有关,我只能说remake永远的神

嵌套查询

像我这种水平比较低的初学者一般用xml来做这种事情

子查询

子查询实际上是按照查询嵌套处理,也就是走了两遍查询
最简单的例子,学生+老师,学生表里有id,name,teacher_id,老师表里有id,name,teacher_id为该学生对应的老师,现在要求用子查询查询所有学生的id,name和对应的老师name

首先,建表,不做赘述
然后,建一个新项目,结构大致如图
在这里插入图片描述
当然Mapper.xml可以直接放到java下的mapper包下,我这里放到了resources下,效果是一样的
再然后写一下实体类,注意这里Student类中对应teacher_id的属性是Teacher类对象
写一下Mapper接口的方法,这里由于没有在TeacherMapper中实现任何操作,所以TeacherMapper不用新建,我这里新建是为了好看(振声,查询学生的方法:

List<Student> getStudents();

接着配置xml,因为是对student的查询,所有根本不用TeacherMapper.xml,直接上StudentMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
       PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
       "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hoppi.mapper.StudentMapper">

   <select id="getStudents" resultMap="student_info">
       select * from student
   </select>
   
   <resultMap id="student_info" type="Student">
       <association property="teacher" column="teacher_id" javaType="Teacher" select="getTeacher"/>
   </resultMap>
   
   <select id="getTeacher" resultType="Teacher">
       select * from teacher where id = #{teacher_id}
   </select>
   
</mapper>

分析标签:

  • 第一个select的内容是查询学生表的所有字段,返回值是自己定义的类型student_info
  • resultMap的内容是自定义student_info,类型为Student类(我在这里使用了别名),association为一对一复杂对象映射,其中property为Student类中的属性名,column为表中字段,javaType为该字段/属性对应Java类型,select为嵌套查询语句,调用下面的getTeacher
  • 第二个select的内容是查询id为传入参数(这里是调用它的getStudents传入的teacher_id,当然由于只传入一个参数,所以名字可以随便取,叫id也行)的老师表的所有字段,返回值是Teacher

写一个测试类跑一下,

package com.hoppi.mapper;

import com.hoppi.pojo.Student;
import com.hoppi.utils.MybatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

public class StudentMapperTest {
    @Test
    public void Teat(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        for (Student student : mapper.getStudents()) {
            System.out.println("ID:" + student.getId() + "\tName:" + student.getName() + "\tTeacher:" + student.getTeacher().getName());
        }
        sqlSession.close();
    }
}

输出:在这里插入图片描述

联表查询

连表查询实际上是按照结果嵌套处理,真正嵌套的是查询得到的结果
继续用上面那个例子,这次要求联表查询
显然,用sql语句表达就是很简单的一句话

select s.id,s.name,t.name from student s,teacher t where s.teacher_id=t.id

实现方式如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
       PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
       "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hoppi.mapper.StudentMapper">

   <select id="getStudents" resultMap="student_info">
       select s.id sid,s.name sname,t.name tname from student s,teacher t where s.teacher_id=t.id
   </select>
   
   <resultMap id="student_info" type="Student">
       <result property="id" column="sid"/>
       <result property="name" column="sname"/>
       <!-- association与result类似,但对象是实体类 -->
       <association property="teacher" javaType="Teacher">
           <result property="name" column="tname"/>
       </association>
   </resultMap>
   
</mapper>

分析标签:

  • select即联表查询语句,获取到的sid、sname、tname是我们需要的,resultMap依旧对应自己定义的类型student_info
  • resultMap即我们自定义的类型,依然是Student类,其中resultassociation对应Student中的属性,result中property为属性名,column为查询到的列名,之所以这里需要在sql语句中重命名是因为如果直接用s.id这种形式会无法解析得到对应的值association中property同样为属性名,javaType为对应java类型,其中的result对应该java类型中的属性

听起来绕得一批,实际上就是属性的嵌套

多对一与一对多

显然,上面的不管是子查询还是联表查询都是以多对一的关系进行查询,即多个学生对应一个老师,以学生为主体
现在换一个问题,一个老师对应多个学生,要查询所有老师的id、name以及教的学生的id、name
表还是那个表,但pojo类需要做出对应的改变,Student类中teacher属性改为int类型的teacher_id,Teacher类中添加List<Student> students属性
容易看出,这时的查询已经变成了以老师为主体
这里用联表查询的方式来实现一下

来写一下TeacherMapper.xml的select

<select id="getTeachers" resultMap="teacher_info">
   select t.id tid,t.name tname,s.id sid,s.name sname from student s,teacher t where s.teacher_id=t.id
</select>

<resultMap id="teacher_info" type="Teacher">
   <result property="id" column="tid" />
   <result property="name" column="tname" />
   <!-- association也与result类似,但对象是集合 -->
   <!-- ofType用于指定对象的所属javaBean类,通常用于集合指定的泛型 -->
   <collection property="students" ofType="Student">
       <result property="id" column="sid" />
       <result property="name" column="sname" />
       <result property="teacher_id" column="tid" />
   </collection>
</resultMap>

测试类试一下

package com.hoppi.mapper;

import com.hoppi.pojo.Student;
import com.hoppi.pojo.Teacher;
import com.hoppi.utils.MybatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

public class TeacherMapperTest {
   @Test
   public void Test(){
       SqlSession sqlSession = MybatisUtil.getSqlSession();
       TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
       for (Teacher teacher : mapper.getTeachers()) {
           System.out.println("老师姓名:" + teacher.getName() + "\t老师ID:" + teacher.getId() + "\t学生名单:");
           for (Student student : teacher.getStudents()) {
               System.out.println("\t学生姓名:" + student.getName() + "\t学生ID:" + student.getId());
           }
       }
       sqlSession.close();
   }
}

运行结果:
在这里插入图片描述

同样的,子查询也适用于一对多,xml中select如下


   <select id="getTeachers" resultMap="teacher_info">
       select * from teacher
   </select>

   <resultMap id="teacher_info" type="Teacher">
       <!--这里加一个属性与列名同名的result是因为下面的collection对应的列名也是id,不加的话Teacher本身的id就会为0-->
       <result property="id" column="id" />
       <collection property="students" column="id" javaType="ArrayList" ofType="Student" select="getStudents" />
   </resultMap>

   <select id="getStudents" resultType="Student">
       select * from student where teacher_id=#{id}
   </select>

动态SQL

xml标签

常用标签:if, choose, when, otherwise, where, trim, set, foreach

  • if即条件判断,若条件为真,则执行标签内的sql语句
    示例:
<if text ="条件">
	拼接的sql语句
</if>
  • choose类似于swich,与when和otherwise一同使用
    示例:
select * from 表名 where
<choose>
    <when test="条件1">
        拼接的sql语句1
    </when>
    <when test="条件2">
        拼接的sql语句2
    </when>
    <otherwise>
    	拼接的sql语句3
    </otherwise>
</choose>

当条件1为真时,执行语句1,跳过剩余语句;条件1为假时,若条件2为真,执行语句2,跳过剩余语句,以此类推,若所有when都不满足,则执行otherwise中的语句

  • where元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。(文档原话)
    示例:
select * from 表名
<where>
    <if test="条件1">
        拼接的sql语句1
    </if>
    <if test="条件2">
        and 拼接的sql语句2
    </if>
</where>

当条件1、2均为真时,执行select * from 表名 where 拼接的sql语句1 and 拼接的sql语句2;当1为假,2为真时执行select * from 表名 where 拼接的sql语句2

  • set用于update,会自动删除拼接的sql语句中多余的逗号
    示例:
update 表名
<set>
	<if test="条件1">
        字段1=传入值1,
    </if>
    <if test="条件2">
        字段2=传入值2,
    </if>
    <if test="条件3">
        字段3=传入值3
    </if>
</set>
where 定位语句

其中set的作用为,当条件3为假而其它两个条件不全为假时去除返回sql语句末尾的逗号

  • trim起的作用类似于where和set,但它却是可定制的

和 where 元素等价的自定义 trim 元素为:

<trim prefix="WHERE" prefixOverrides="AND |OR ">
 ...
</trim>

prefix即开头自动添加语句,prefixOverrides即开头自动删除语句(如果有的话),注意空格

和set元素等价的自定义trim元素为:

<trim prefix="SET" suffixOverrides=",">
 ...
</trim>

suffixOverrides即末尾自动删除语句,可推测,suffix是末尾自动添加语句

  • foreach比较复杂,可以参考一下这篇文章
    简单的说明一下↓

如果是select...where...(or)的话,那么就应该使用

<foreach collection="list" item="item" open="(" separator="or" close=")">
		#{item}
</foreach>

如果是select...in...这种,那么就应该使用

<foreach collection="list" item="item" open="(" separator="," close=")">
		#{item}
</foreach>

如果是insert into...values...这种,那么就要使用

<!-- 用于list插入多条单字段记录 -->
<foreach collection="list" item="item" separator=",">
		(#{item})
</foreach>

<!-- 用于map插入多条多字段记录 -->
<foreach collection="map" index="key" item="value" separator=",">
		(#{key},#{value})
</foreach>
  • sql,这是用于实现sql代码复用的标签,当在Mapper.xml中出现大量重复代码时,会影响美观,此时需要用sql标签对其进行封装(需设置id),使用的时候在需要用到的地方通过include标签的refid引用其id即可

注解中的动态SQL

注解中的动态SQL和xml中的相同,区别在于使用<script>标签,官方文档的示例如下:在这里插入图片描述

缓存

Mybatis的缓存分为一级和二级缓存。一级缓存对应且存在于一个SqlSession开启到关闭的过程中,一级缓存默认开启且不可关闭;二级缓存对应一个mapper对象,当SqlSession关闭或提交时,其一级缓存会存到对应mapper的二级缓存中,之后开启此mapper对应sqlSession会直接从二级缓存中读取(如果有的话)
具体的请参考这篇文章

再见

就写到这吧,去水Spring笔记了("▔□▔)/

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值