MyBatis 原理篇(个人笔记,勿看)

本文详细介绍了MyBatis的使用,包括简介、HelloWord示例、环境配置、增删改查操作、参数获取方式、多对一和一对多映射、动态SQL以及缓存机制。阐述了MyBatis获取参数值的两种方式,还说明了一级缓存和二级缓存的使用方法及配置要点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. MyBatis 简介

  • 有 MyBatis 就不需要 dao 层的实现类,当 service 直接来调用 dao 接口中的方法,他就能自动去实现 sql 语句

  • 定制化 sql ,就是自己随意写 sql 语句

  • 存储过程:使用 sql 语句逻辑代码来实现的一个查询过程。即用 sql 写一段代码

  • <!DOCTYPE configuration。<!DOCTYPE 后面的单词就是 xml 文件的根标签

HelloWord

package com.xp.entity;

public class User {
    String uname;
    String upass;

    @Override
    public String toString() {
        return "User{" +
                "uname='" + uname + '\'' +
                ", upass='" + upass + '\'' +
                '}';
    }

    public String getUname() {
        return uname;
    }

    public void setUname(String uname) {
        this.uname = uname;
    }

    public String getUpass() {
        return upass;
    }

    public void setUpass(String upass) {
        this.upass = upass;
    }

}

UserMapper 类:

package com.xp.mapper;

import com.xp.entity.User;

public interface UserMapper {
    User getUserByUid(String uname);
}

核心配置文件 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>
    <settings>
        <!--建议显示的指定我们需要配置的值,防止版本更新带来的问题-->
        <!--开启驼峰命名规则-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mysqltest?characterEncoding=utf-8"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>

    <!--引入映射文件-->
    <mappers>
        <!--<mapper resource="org/mybatis/example/BlogMapper.xml"/>-->
        <!--也可以使用package <package name=""></package>-->
        <mapper resource="UserMapper.xml"></mapper>
    </mappers>
</configuration>

映射配置文件 UserMapper.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.xp.mapper.UserMapper">
    <!--id 是接口中的方法名(因为绑定:接口全限定名和映射文件绑定)
    <select>:定义查询语句
    id:设置 SQL 语句的唯一标识
    resultType:结果类型,即实体类的全限定名
    -->
    <select id="getUserByUid" resultType="com.xp.entity.User" parameterType="java.lang.String">
        select * from user where uname= #{uname}
    </select>
</mapper>

Test 类:

import com.xp.entity.User;
import com.xp.mapper.UserMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

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




public class MyTest {
    /**
     * 1、接口式编程
     * 	原生:		Dao		====>  DaoImpl
     * 	mybatis:	Mapper	====>  xxMapper.xml
     *
     * 2、SqlSession代表和数据库的一次会话;用完必须关闭;
     * 3、SqlSession和connection一样她都是非线程安全。每次使用都应该去获取新的对象。
     * 4、mapper接口没有实现类,但是mybatis会为这个接口生成一个代理对象。
     * 		(将接口和xml进行绑定)
     * 		EmployeeMapper empMapper =	sqlSession.getMapper(EmployeeMapper.class);
     * 5、两个重要的配置文件:
     * 		mybatis的全局配置文件:包含数据库连接池信息,事务管理器信息等...系统运行环境信息
     * 		sql映射文件:保存了每一个sql语句的映射信息:
     * 					将sql抽取出来。
     */
    @Test
    public void test01() throws IOException {
        InputStream is= Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory=
                new SqlSessionFactoryBuilder().build(is);
        SqlSession sqlSession=sqlSessionFactory.openSession();
        // getMapper():会通过动态代理动态生成 UserMapper 的代理实现类
        UserMapper mapper=sqlSession.getMapper(UserMapper.class);
        User user=mapper.getUserByUid("zs");
        System.out.println(user);
    }
}

在这里插入图片描述

  • 类里面属性的名字和数据库中的字段名或者字段名的别名要一致

Environment

  • resource :在类路径下访问资源文件
  • url:在网络路径或磁盘路径下访问资源文件
<?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>
    <settings>
        <!--建议显示的指定我们需要配置的值,防止版本更新带来的问题-->
        <!--开启驼峰命名规则-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
    <!--
    <environments>:设置数据库的环境
    default:设置默认的数据库环境
    -->
    <environments default="development">
        <!-- environment:设置某个具体的数据库环境 -->
        <environment id="development">
            <!-- type="MANAGED" 被管理的,就是谁能管理事务就让谁管理,比如 Spring 就能管理-->
            <transactionManager type="JDBC"/>
            <!--type=POOLED|UNPOOLED|JNDI-->
            <!--
                POOLED:使用 mybatis 默认的自带的连接池(使用连接池会将当前连接进行缓存)
                UNPOOLED:不使用数据库连接池,也就是每次连接都会创建一个新的连接
                JNDI:调用上下文的数据源(下面的 dataSource 就是一个数据源)
            -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mysqltest?characterEncoding=utf-8"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>

    <!--引入映射文件-->
    <mappers>
        <!--<mapper resource="org/mybatis/example/BlogMapper.xml"/>-->
        <!--也可以使用package <package name=""></package>-->
        <mapper resource="UserMapper.xml"></mapper>
    </mappers>
</configuration>
  • 核心配置文件的标签是有先后顺序的

typeAliases

    <typeAliases>
        <!-- type:java类型,一般填类的全限定名,若只设置 type,默认的别名就是类名,且不区分大小写。若要自己设置别名,加一个 alias="要设置的名字" -->
        <!--<typeAlias type="com.xp.entity.User" alias="u"></typeAlias>-->
        <!-- 还有一种用法:-->
        <package name="com.xp.entity"/> <!--这个就是为这个包名下的所有类创建别名,别名为类名-->
    </typeAliases>

mapper 和 xml 的增删改查

JDBC 的事务必须手动提交,两种方式,sqlSession.commit() 或者 openSession(true)

实体类emp:

public class Emp {
    Integer eid;
    String ename;
    String sex;

    public Emp(Integer eid, String ename, String sex) {
        this.eid = eid;
        this.ename = ename;
        this.sex = sex;
    }

    public Emp(String ename, String sex) {
        this.ename = ename;
        this.sex = sex;
    }

    public Integer getEid() {
        return eid;
    }

    public void setEid(Integer eid) {
        this.eid = eid;
    }

    public String getEname() {
        return ename;
    }

    public void setEname(String ename) {
        this.ename = ename;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "eid=" + eid +
                ", ename='" + ename + '\'' +
                ", sex='" + sex + '\'' +
                '}';
    }
}

EmpMapper类:

package com.xp.mapper;

import com.xp.entity.Emp;

import java.util.List;

public interface EmpMapper {
    //增
    Integer addEmp(Emp emp);
    //删
    Integer deleteEmp(Integer eid);
    //改
    Integer updateEmp(Emp emp);
    //查by id
    Emp getEmpById(Integer eid);
    //查 all
    List<Emp>getAllEmp();
}

EmpMapper.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.xp.mapper.EmpMapper">
    <!--id 是接口中的方法名(因为绑定:接口全限定名和映射文件绑定)
    <select>:定义查询语句
    id:设置 SQL 语句的唯一标识
    resultType:结果类型,即实体类的全限定名
    -->

   <!-- Integer addEmp(Emp emp); -->
    <insert id="addEmp" parameterType="com.xp.entity.Emp">
        insert into Emp(ename,sex) values(#{ename},#{sex})
    </insert>
    <!-- Integer deleteEmp(Integer eid);-->
    <delete id="deleteEmp" parameterType="java.lang.Integer">
        delete from Emp where eid=#{eid}
    </delete>
    <!-- Integer updateEmp(Emp emp);-->
    <update id="updateEmp" parameterType="com.xp.entity.Emp">
        update Emp set ename=#{ename},sex=#{sex} where eid=#{eid}
    </update>
    <!-- Emp getEmpById(Integer eid);-->
    <select id="getEmpById" resultType="com.xp.entity.Emp">
        select * from emp where eid=#{eid}
    </select>
    <!-- List<Emp>getAllEmp();-->
    <!--这里的返回值类型填 Emp,因为他会自动把 Emp 放到 List 集合中-->
    <select id="getAllEmp" resultType="com.xp.entity.Emp">
        select * from emp
    </select>
 </mapper>

Test 类:

public class MyTest
{
    @Test
    public void test01() throws IOException {
        InputStream is= Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory=
                new SqlSessionFactoryBuilder().build(is);
        SqlSession sqlSession=sqlSessionFactory.openSession(true); //设置为 true ,事务自动提交
        EmpMapper mapper=sqlSession.getMapper(EmpMapper.class);
        //测试增加员工
        //System.out.println(mapper.addEmp(new Emp("李四","男")));
        //测试查询员工 byid
        //System.out.println(mapper.getEmpById(3));
        //查询所有员工
        /*for (Emp emp : mapper.getAllEmp()) {
            System.out.println(emp);
        }*/
        //更新员工信息
        //System.out.println(mapper.updateEmp(new Emp(2,"ls","女")));
        //删除员工信息
        //System.out.println(mapper.deleteEmp(1));
    }
}

通过 package 管理映射文件的引入

可以在 resources 下面创建一个包,通过 package 的方式,可以把那个包下的所有 xml 文件引入进来,如:

	<mappers>
        <!-- 这种写法要求 mapper 接口和 mapper 映射文件必须在同一个包下-->
        <package name="com.xp.mapper"/>
    </mappers>

在这里插入图片描述
在这里插入图片描述

MyBatis 获取参数值的两种方式 ${} 和 #{}

#{}:PreparedStatement(通过通配符赋值,可以防止 sql 注入)
${}:Statement(字符串拼接,需要注意单引号问题)

使用建议:建议使用 #{},在特殊情况下,需要使用 ${} ,比如模糊查询和批量操作

MyBatis 实现添加时获取自动生成的主键

在 JDBC 里面:

PreparedStatement ps=con.prepareStatement("",1)//这个1就是允许获取自动生成的主键的意思
...
ResultSet rs=ps.getGenerateKeys() //获取自动生成的主键
rs.next();
int id=rs.getInt(1) //获取自动生成的主键

在 MyBatis 里面:

    <!--
        useGeneratedKeys:可以使用自动生成的主键
        keyProperty:将获取到的自动生成的主键赋值给Emp(传递过来的参数)哪个属性
    -->
<insert id="addEmp" parameterType="com.xp.entity.Emp" useGeneratedKeys="true" keyProperty="eid">
        insert into Emp(ename,sex) values(#{ename},#{sex})
</insert>

MyBatis 获取不同参数值的方式1

不同的参数类型,${} 和 #{} 的不同取值方式:
1、当传输参数为单个 String 或基本数据类型和其包装类
#{}:可以以任意的名字获取参数值
${}:只能以 ${value} 或 ${_parameter} 获取

2、当传输参数为 JavaBean 时
#{} 和 ${} 都可以通过属性名直接获取属性值,但是要注意 ${} 的单引号问题

3、当传输多个参数时
两种方式:
(1)键为arg0,arg1…argN
(2)键为 param1,param2…paramN
#{}:#{arg0},#{param1}
: {}: :{arg0},${param1}
在这里插入图片描述

 Emp getEmpById(Integer eid,String ename);
<select id="getEmpById" resultType="com.xp.entity.Emp">
        select * from emp where eid=#{arg0} and ename=#{arg1}
</select>

4、当传输参数为 map 时
#{} 和 ${} 都可以通过属性名直接获取属性值,但是要注意 ${} 的单引号问题

5、命名参数
可以通过注解 @Param 为 map 指定键的名字
#{} 和 ${} 都可以通过属性名直接获取属性值,但是要注意 ${} 的单引号问题

6、当传输参数为 List 或 Array,MyBatis 会将 List 或 Array 放在 map 中
List 以 list 为键,Array 以 array 为键

多对一自定义映射

Emp 类(一定要有空的构造器):

package com.xp.entity;

public class Emp {
    Integer eid;
    String ename;
    String sex;
    Dept dept; // 一个员工对应一个部门

    public Emp() {
    }

    public Dept getDept() {
        return dept;
    }

    public void setDept(Dept dept) {
        this.dept = dept;
    }

    public Emp(Integer eid, String ename, String sex, Dept dept) {
        this.eid = eid;
        this.ename = ename;
        this.sex = sex;
        this.dept = dept;
    }

    public Emp(String ename, String sex) {
        this.ename = ename;
        this.sex = sex;
    }

    public Integer getEid() {
        return eid;
    }

    public void setEid(Integer eid) {
        this.eid = eid;
    }

    public String getEname() {
        return ename;
    }

    public void setEname(String ename) {
        this.ename = ename;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "eid=" + eid +
                ", ename='" + ename + '\'' +
                ", sex='" + sex + '\'' +
                ", dept=" + dept +
                '}';
    }
}

EmpMapper.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.xp.mapper.EmpMapper">

    <resultMap id="empdept" type="com.xp.entity.Emp">
        <!--id 表示主键的 column 和 property 的对应关系-->
        <id column="eid" property="eid"></id>
        <!-- column 对应数据库字段,property 对应类的属性名-->
        <result column="ename" property="ename"></result>
        <result column="sex" property="sex"></result>
        <result column="did" property="dept.did"></result>
        <result column="dname" property="dept.dname"></result>
    </resultMap>
    
<!-- List<Emp>getAllEmp();-->
<!--这里的返回值类型填 Emp,因为他会自动把 Emp 放到 List 集合中-->
<!--resultMap:实现将查询结果映射为复杂类型的pojo(就像这里的Emp类,他还包含一个类Dept,所以可以将查询结果做个映射)-->
<select id="getAllEmp" resultMap="empdept">
        select e.eid,e.ename,e.sex,d.did,d.dname from emp e left join dept d on e.did=d.did
    </select>
</mapper>

使用 association 完成多对一映射

其他类和上面一样
EmpMapper.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.xp.mapper.EmpMapper">

    <resultMap id="empdept" type="com.xp.entity.Emp">
        <!--id 表示主键的 column 和 property 的对应关系-->
        <id column="eid" property="eid"></id>
        <!-- column 对应数据库字段,property 对应类的属性名-->
        <result column="ename" property="ename"></result>
        <result column="sex" property="sex"></result>
        <!--association:写嵌套的那个类-->
        <association property="dept" javaType="com.xp.entity.Dept">
            <id column="did" property="did"></id>
            <result column="dname" property="dname"></result>
        </association>
    </resultMap>
<!-- List<Emp>getAllEmp();-->
<!--这里的返回值类型填 Emp,因为他会自动把 Emp 放到 List 集合中-->
<select id="getAllEmp" resultMap="empdept">
        select e.eid,e.ename,e.sex,d.did,d.dname from emp e left join dept d on e.did=d.did
    </select>
</mapper>

多对一分步查询

EmpMapper.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.xp.mapper.EmpMapper">

    <resultMap id="empdept" type="com.xp.entity.Emp">
        <!--id 表示主键的 column 和 property 的对应关系-->
        <id column="eid" property="eid"></id>
        <!-- column 对应数据库字段,property 对应类的属性名-->
        <result column="ename" property="ename"></result>
        <result column="sex" property="sex"></result>
<!--
select :去找到一个 sql ,select 的值就是这个sql的id ,查询结果为 dept 的来给 dept 赋值
id 就是一个方法名,方法名在接口里面,所以完整的表示应该为:接口全限定名.方法名
column:就是把选中的那个字段作为分步查询的条件
-->
        <association property="dept" javaType="com.xp.entity.Dept" select="com.xp.mapper.DeptMapper.getDeptById" column="did">
        </association>
    </resultMap>
<!-- List<Emp>getAllEmp();-->
<!--这里的返回值类型填 Emp,因为他会自动把 Emp 放到 List 集合中-->
<select id="getAllEmp" resultMap="empdept">
        select e.eid,e.ename,e.sex,e.did from emp
    </select>
</mapper>

DeptMapper.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.xp.mapper.DeptMapper">
<!--这个id标识的是一个方法名,所以只需要接口全限定名.方法名就可以在工程里面唯一标识这个 select-->
    <select id="getDeptById" resultType="com.xp.entity.Dept">
        select did,dname from dept where did=#{did}
    </select>
</mapper>

分步查询的延迟加载

对于上面三种多对一的写法中,延迟加载只针对分步查询,延迟加载就是要用的时候才加载,延迟加载又叫懒加载。在核心配置文件(mapper-config.xml) 中的 setting 标签进行配置

<settings>
	<!-- 开启全局性设置懒加载 -->
	<setting name="lazyLoadingEnabled" value="true"/>
	<!-- 开启按需加载 -->
	<setting name="aggressiveLazyLoading" value="false"/>
</settings>

一对多自定义映射

案例描述:根据 Dept_id 查出来一个部门的所有员工信息

public interface DeptMapper {
    //public Dept getDeptById(Integer id);
    public List<Dept> getDeptEmpsById(Integer 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.xp.mapper.DeptMapper">
    <resultMap id="deptemp" type="Dept">
        <id column="did" property="did"></id>
        <result column="dname" property="dname"></result>
        <!-- association是用于一对一和多对一,而collection是用于一对多的关系 -->
        <!--JavaType和ofType都是用来指定对象类型的,但是JavaType是用来指定pojo中属性的类型,而ofType指定的是映射到list集合属性中pojo的类型-->
        <collection property="emps" ofType="Emp">
            <id column="eid" property="eid"></id>
            <result column="ename" property="ename"></result>
            <result column="sex" property="sex"></result>
        </collection>
    </resultMap>
    <!-- public List<Dept> getDeptEmpsById(Integer id) -->
    <select id="getDeptEmpsById" resultMap="deptemp">
        select d.did,d.dname,e.eid,e.ename,e.sex from dept d left join emp e on d.did=e.did where d.did=#{did}
    </select>
</mapper>

一对多分步查询

DeptMapper.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.xp.mapper.DeptMapper">
    <resultMap id="deptemp" type="Dept">
        <id column="did" property="did"></id>
        <result column="dname" property="dname"></result>
        <collection property="emps" ofType="Emp" select="com.xp.mapper.EmpMapper.getEmpById" column="did"></collection>
    </resultMap>
    <!-- public List<Dept> getDeptEmpsById(Integer id) -->
    <select id="getDeptEmpsById" resultMap="deptemp">
        select d.did,d.dname from dept d where did=#{did}
    </select>
</mapper>

EmpMapper.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.xp.mapper.EmpMapper">
        <!--Emp getEmpById(Integer did)-->
        <select id="getEmpById" resultType="Emp">
                select * from emp where did=#{did}
        </select>
</mapper>

这里注意一个问题就是,如果 column 有多个值需要传的话,就可以用 map 的形式,即 {did=did},前面那个 did 就是你后面EmpMapper.xml sql里面的#{}中的那个did,后面的 did 就是DeptMapper.xml <id column="did" property="did"></id>中的property查出来的值

在这里插入图片描述

还有一个问题就是你不想指定全局延迟加载的时候,可以用 fetchType ,指定某个 sql 的延迟加载
在这里插入图片描述

动态 SQL

<if test=""></if>: 通过 test 表达式,拼接 SQL
<where></where>:Where可以在处理条件时,自动的去掉以and、or开始的字符串。如果把 and 写在语句的尾,该报错还是会报错。不过可以用 trim 解决 and 在语句末尾的情况
<trim>:事实上trim标签有点类似于replace效果。
 trim 属性
                prefix:前缀覆盖并增加其内容
                suffix:后缀覆盖并增加其内容
                prefixOverrides:前缀判断的条件
                suffixOverrides:后缀判断的条件
                
<set>:主要是用于解决修改操作中能够 SQL 语句中可能多出逗号的问题。一般用于update语句,生成set column=?

<choose>:主要是用于分支判断,类似于 Java 中的 switch case ,只会满足所有分支中的一个


动态 SQL 之 if

mybatis 映射文件中,if标签判断字符串相等,两种方式:因为mybatis映射文件,是使用的ognl表达式,所以在判断字符串sex变量是否是字符串Y的时候使用

<test="sex=='Y'.toString()">或者<test = 'sex== "Y"'>

因为mybatis会把’Y’解析为字符,java是强类型语言,所以不能这样写。

EmpMapper类:

public interface EmpMapper {
   public List<Emp> getAllEmpByCondition(Emp emp);
}

EmpMapper.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.xp.mapper.EmpMapper">
        <!-- public List<Emp> getAllEmpByCondition(Emp emp) -->
        <select id="getAllEmpByCondition" resultType="com.xp.entity.Emp" parameterType="com.xp.entity.Emp">
                select eid,ename,sex from emp where
                1=1
                <if test="eid!=null">and eid=#{eid}</if>
                <if test="ename!='' and ename!=null">and ename=#{ename}</if>
                <if test="sex==''.toString() or sex==''.toString()"> and sex=#{sex}</if>
        </select>
</mapper>

动态 SQL 之 where

和上面等价的写法:

EmpMapper.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.xp.mapper.EmpMapper">
        <!-- public List<Emp> getAllEmpByCondition(Emp emp) -->
        <select id="getAllEmpByCondition" resultType="com.xp.entity.Emp" parameterType="com.xp.entity.Emp">
                select eid,ename,sex from emp
                <where>
                    <if test="eid!=null">and eid=#{eid}</if>
                    <if test="ename!='' and ename!=null">and ename=#{ename}</if>
                    <if test="sex==''.toString() or sex==''.toString()"> and sex=#{sex}</if>
                </where>
        </select>
</mapper>

动态 SQL 之 trim

等价上面的 EmpMapper.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.xp.mapper.EmpMapper">
        <!-- public List<Emp> getAllEmpByCondition(Emp emp) -->
        <select id="getAllEmpByCondition" resultType="com.xp.entity.Emp" parameterType="com.xp.entity.Emp">
                select eid,ename,sex from emp
                <!--
                     <trim>:截取并拼接
                     prefix:在操作的 SQL 前加入某些内容
                     prefixOverrides:把操作的 SQL 语句前的某些内容去掉
                     suffix:在操作的 SQL 后加入某些内容
                     suffixOverrides:把操作的 SQL 语句后的某些内容去掉
                -->
                <trim prefix="where" suffixOverrides="and|or">
                    <if test="eid!=null">eid=#{eid} and</if>
                    <if test="ename!='' and ename!=null">ename=#{ename} and</if>
                    <if test="sex==''.toString() or sex==''.toString()">sex=#{sex}</if>
                </trim>
        </select>
</mapper>

动态 SQL 之 choose

<choose>选择一个条件进行判断
EmpMapper.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.xp.mapper.EmpMapper">
        <!-- public List<Emp> getAllEmpByCondition(Emp emp) -->
        <select id="getAllEmpByCondition" resultType="com.xp.entity.Emp" parameterType="com.xp.entity.Emp">
                select eid,ename,sex from emp
                <!--
                     <trim>:截取并拼接
                     prefix:在操作的 SQL 前加入某些内容
                     prefixOverrides:把操作的 SQL 语句前的某些内容去掉
                     suffix:在操作的 SQL 后加入某些内容
                     suffixOverrides:把操作的 SQL 语句后的某些内容去掉
                -->
                <where>
                <choose>
                    <when test="eid!=null"> eid=#{eid} </when>
                    <when test="ename!='' and ename!=null">ename=#{ename}</when>
                    <when test="sex==''.toString() or sex==''.toString()">sex=#{sex}</when>
                </choose>
                </where>
        </select>
</mapper>

批量删除

三种方法
第一种:用 in
EmpMapper.Java 类:

package com.xp.mapper;

import com.xp.entity.Emp;

import java.util.List;

public interface EmpMapper {
	// 通过 eid 所组成的字符串实现批量删除
    public void deleteMoreEmp(String eids);
}

EmpMapper.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.xp.mapper.EmpMapper">
        <!--public void deleteMoreEmp(String eids)-->
      <delete id="deleteMoreEmp" parameterType="java.lang.String">
              delete from emp where eid in (${value})
      </delete>
</mapper>

测试类:

public class MyTest
{
    @Test
    public void test01() throws IOException {
        InputStream is= Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory=
                new SqlSessionFactoryBuilder().build(is);
        SqlSession sqlSession=sqlSessionFactory.openSession(true); //设置为 true ,事务自动提交
        EmpMapper mapper=sqlSession.getMapper(EmpMapper.class);
        mapper.deleteMoreEmp("1,2,3");
    }

}

第二种方法:
使用 foreach 实现批量删除
EmpMapper.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.xp.mapper.EmpMapper">
    <!-- public void deleteMoreByList(List<Integer>emps) -->
    <delete id="deleteMoreByList">
        delete from emp where eid in(
        <!--这里的 collection 不写前面 List 的名字emps ,而写 list 是因为:
            当传输参数为 List 或 Array,MyBatis 会将 List 或 Array 放在 map 中
List 以 list 为键,Array 以 array 为键
        -->
        <!--
            <foreach>:对一个数组或集合进行遍历
            collection: 指定要遍历的集合或数组
            item:设置别名
            close:设置循环体的结束内容
            open:设置循环体的开始内容
            separator:设置每一次循环的分隔符
            index:若遍历的是 List,index 代表下标,若遍历的是 map,index 代表键
        -->
            <foreach collection="list" separator="," item="emp">
                #{emp}
            </foreach>
        )
    </delete>
</mapper>

EmpMapper.Java 类:

public interface EmpMapper {
    // 通过 list 集合实现批量删除
    public void deleteMoreByList(List<Integer>emps);
}

动态 SQL 之 sql

    <!-- <sql>: 设置一段 SQL 片段,即公共 SQL,可以被当前映射文件中所有SQL语句所访问-->
    <sql id="selectemp">select * from emp</sql>
然后通过 :
	<include refid="selectemp"></include>
进行使用

MyBatis 的缓存

MySQL 一般是把数据存在磁盘中,缓存就是把数据存放在内存中

  • 二级缓存在操作实体类的时候,这个实体类必须实现了 Serializable 接口
  • 缓存回收策略:就是内存的大小是有限的,当内存放不下的时候,就应该清理缓存,这个就是指清理缓存的策略

缓存机制简介

(1)MyBatis 是一个包含非常强大的查询缓存特性,它可以非常方便地配置和定制,缓存可以极大的提升查询效率
(2)MyBatis 系统中默认定义了两级缓存

  • 一级缓存
  • 二级缓存
    (3)默认情况下,只有一级缓存(SqlSession 级别的缓存,也称为本地缓存)开启
    (4)二级缓存需要手动开启和配置,他是基于 namespace 级别的缓存
    (5)为了提高扩展性,MyBatis 定义了缓存接口 Cache ,我们可以通过实现 Cache 接口来自定义二级缓存

一级缓存的使用

(1)一级缓存,即本地缓存,作用域默认 sqlSession,当 Session flush 或 close 后,该 Session 中所有 Cache 将被清空
(2)本地缓存不能关闭,但可以调用 clearCache() 来清空本地缓存,或者改变缓存的作用域
(3)在 MyBatis3.1 之后,可以配置本地缓存的作用域,在 MyBatis.xml 中配置

二级缓存的使用

(1)二级缓存,全局作用缓存
(2)二级缓存默认不开启,需要手动配置
(3)MyBatis 提供二级缓存的接口以及实现,缓存实现要求 pojo 实现 Serializable 接口
(4)二级缓存在 SQLSession 关闭或提交之后才会生效
(5)二级缓存的使用步骤:
①全局配置文件中开启二级缓存 <setting name="cacheEnable" value="true">
②需要使用二级缓存的映射文件处使用 cache 配置缓存 <cache />
③注意:POJO 需要实现 Serializable 接口
(6)二级缓存相关的属性
eviction="FIFO":缓存回收策略
LRU:最近最少使用的,移除最长时间不被使用的对象
FIFO:先进先出,按对象进入缓存的顺序来移除它们
SOFT:软引用,移除基于垃圾回收器状态和软引用规则的对象
WEAK:弱引用,移除基于垃圾回收器状态和弱引用规则的对象

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值