Mybatis的进阶知识点

动态SQL
if标签

if标签中的test属性是必须的,if标签中test属性的值是true或者false

如果值是true,那么if标签中的sql语句就会拼接,反之则不会拼接

test的值的取值:

  1. 当使用@Param注解,那么要出现的是@Param注解指定的参数名,

  2. 当没有使用@Param注解要使用param1,param2,arg0,arg1...

  3. 当使用了pojo的实体类,那么test中出现的是pojo的属性名

    <if test=""></if>

要给where加上一个恒等的条件,然后在拼接的每个sql语句当中加上and

sql语句当中是对应的字段名=#{}

List<Car> selectByMultiCondition(@Param("id") Long id, @Param("brand") String brand, @Param("guidePrice") Double guidePrice);
}


<select id="selectByMultiCondition" resultType="Car">
    select *
    from t_car
    where 1=1
    <if test="id != null and id !=''">
       and id=#{id}
    </if>
    <if test="brand !=null and brand !=''">
        and brand=#{brand}
    </if>
    <if test="guidePrice !=null and guidePrice !=''">
        and guide_price=#{guidePrice}
    </if>
</select>
where标签

where标签的作用:

  • 所有条件都为空时,where标签保证不会生成where子句

  • 自动去除某些条件前面多余的and或or

    <select id="selectByMultiCondition" resultType="Car"> select * from t_car <where> <if test="id != null and id !=''"> id=#{id} </if> <if test="brand !=null and brand !=''"> and brand=#{brand} </if> <if test="guidePrice !=null and guidePrice !=''"> and guide_price=#{guidePrice} </if> </where> </select>
trim标签

trim标签的属性:

  • prefix:在trim标签的语句前添加内容
  • suffix:在trim标签的语句后添加内容
  • prefixOverrides:前缀去掉
  • suffixOverrides:后缀去掉

所有语句都为空就不加where

// prefix或suffix是在所有语句前面添加前缀或后缀
// 把trim标签语句内的and去掉
<trim prefix="where" suffixOverrides="and|or">
            <if test="id != null and id !=''">
                 id=#{id} and
            </if>
            <if test="brand !=null and brand !=''">
                 brand=#{brand} and
            </if>
            <if test="guidePrice !=null and guidePrice !=''">
                 guide_price=#{guidePrice}
            </if>
        </trim>
set标签

当所有条件都为空的时候,不会添加set,会自动去除多余的","

<update id="UpdateBySet">
        update t_car
        <set>
         <if test="carNum !=null and carNum!=''">car_num=#{carNum},</if>
        <if test="brand !=null and brand!=''">brand=#{brand},</if>
        <if test="guidePrice!=null and guidePrice!=''">guide_price=#{guidePrice},</if>
        <if test="produceTime !=null and produceTime!=''">produce_time = #{produceTime},</if>
            <if test="carType !=null and carType!=''">car_type = #{carType},</if>
        </set>
        where
        id = #{id}
    </update>
choose when otherwise

这三个标签是在一起使用的,相当于if else if else if else

只有一个分支会被选择

<select id="selectByChoose" resultType="Car">
        select *
        from t_car
        <where>
            <choose>
                <when test="brand!=null and brand!=''">
                   and brand like "%"#{brand}"%"
                </when>
                <when test="guidePrice!=null and guidePrice !=''">
                   and guide_price = #{guidePrice}
                </when>
                <when test="carType !=null and carType !=''">
                   and car_type = #{carType}
                </when>
            </choose>
        </where>
    </select>
forEach标签

forEach底层是map存储的数组,collection的值可以是注解的值或者array,arg0

<!--    forEach标签的属性
        collection:指定的数组或集合
        item:代表集合或数组中的元素
        separator:代表循环之间的分隔符
    	open:是forEach所有语句的最前面以什么开始
        close:是forEach所有语句的最前面以什么结束
-->
int deleteByIds(@Param("ids") Long[] ids);
    <delete id="deleteByIds">
        delete  from t_car
        where id in (
            <foreach collection="ids" item="id" separator=",">
                #{id}
            </foreach>
            )
    </delete>
批量添加
// #{}中的内容是pojo类的属性名
<insert id="insertByCars">
        insert into t_car
        values
            <foreach collection="cars" item="car" separator=",">
                (null,#{car.carNum},#{car.brand},#{car.guidePrice},#{car.produceTime},#{car.carType})
            </foreach>
    </insert>
sql标签与include标签

sql标签用来声明sql片段

include标签将声明的sql片段包含到某个sql语句当中

作用:提高代码的复用性,易于维护

 <sql id="carColumNameSql">
            id,
            car_num as carNum,
            brand,
            guide_price as guidePrice,
            produce_time as produceTime,
            car_type as carType
    </sql>
    <select id="selectByIdResBigMap" resultType="java.util.Map">
        select
            <include refid="carColumNameSql"></include>
        from t_car
    </select>
高级映射
多对一
级联属性映射

多对一:多个主对象对应一个副对象

在设计的时候主对象应包含副对象的类

主对象对应的表是主表,副对象对应的是副表

多对一映射到JVM当中映射的是主对象

public class Student {//主对象
    private Integer sId;
    private String  sName;
    private Clazz clazz;//副对象

 <resultMap id="studentResultMap" type="Student">
        <id property="sId" column="sid"></id>
        <result property="sName" column="sname"></result>
        <result property="clazz.cId" column="cid"></result>
        <result property="clazz.cName" column="cname"></result>
    </resultMap>

    <select id="selectById" resultMap="studentResultMap">
        select
            s.sid,s.sname,c.cid,c.cname
        from t_stu as s
        left join t_clazz as c
        on s.cid=c.cid
        where
            s.sid=#{s.sid}
    </select>
association方法

使用association标签进行映射

<resultMap id="studentResultMapSelectByIdAssociation" type="Student">
        <id property="sId" column="sid"/>
        <result property="sName" column="sname"/>
<!--
    association:关联,一个student对象关联一个clazz对象
    property:提供要映射的POJO类的属性名
    javaType:用来指定要映射的java类型
-->
        <association property="clazz" javaType="Clazz">
            <id property="cId" column="cid"/>
            <result property="cName" column="cname"/>
        </association>
    </resultMap>
分布查询

优点:可复用,可以进行延迟加载

<!--两条sql语句完成多对一的分布查询
    这是第一步,根据学生id查询学生的所有信息,
	property是指定映射的类型,
    select是第二步查询的id,
	column是将哪个参数传给select语句
-->
// Student映射文件对应的配置    主对象
    <resultMap id="studentResultMapByStep" type="student">
        <id property="sId" column="sid"/>
        <result property="sName" column="sname"/>
        <association property="clazz"
                     select="org.example.mapper.ClazzMapper.selectById"
                     column="cId"/>
    </resultMap>
    <select id="selectByIdStep1" resultMap="studentResultMapByStep">
        select sid,sname,cid
        from t_stu where sid=#{sid}
    </select>
// Clazz映射文件对应的配置    副对象
	<select id="selectById" resultType="Clazz">
        select cid,cname from t_clazz where cid=#{cid}
    </select>
延迟加载

延迟加载的核心原理:用的时候再执行查询语句,不用的时候不查询

作用:提高性能

在mybatis当中开启延迟加载,默认情况下是关闭的

这种在association设置fetchType只是局部的设置,只对当前关联的sql语句生效

如果要配置全局设置,要在核心配置文件当中设置

<association fetchType="lazy"/>
一对多

一对多:一个主对象对应多个副对象

主对象的类中有副对象类的集合

collection标签映射
    <resultMap id="clazzResultMap" type="Clazz">
        <id property="cId" column="cid"/>
        <result property="cName" column="cname"/>
<!--
            property:指定主对象中关联的副对象的属性名
            ofType:用来指定集合中的元素类型
-->
        <collection property="students" ofType="Student">
            <id property="sId" column="sid"/>
            <result property="sName" column="sname"/>
        </collection>
    </resultMap>
    
    <select id="selectByCollection" resultMap="clazzResultMap">
        select c.cid,c.cname,s.sid,s.sname
        from t_clazz as c left join t_stu as s on c.cid=s.cid
        where c.cid=#{cid}
    </select>
分布查询
// collection中的property是clazz封装的List<Student>的属性名
// select是select的id
// column是要传入的值
// fetchType是否开启延迟加载


// Clazz的映射文件的配置   主对象
<resultMap id="ClazzResultMapStu" type="Clazz">
        <id property="cId" column="cid"/>
        <result property="cName" column="cName"/>
        <collection  property="students"
                     select="org.example.mapper.StudentMapper.selectById2"
                     column="cid"
                     fetchType="lazy"/>
    </resultMap>

    <select id="selectById1" resultMap="ClazzResultMapStu">
        select cid,cname
        from t_clazz
        where cid=#{cid}
    </select>

// Student的映射文件的配置     副对象
<select id="selectById2" resultType="Student">
        select sid,sname,cid
        from t_stu
        where cid=#{cid}
    </select>
Mybatis的缓存

内存:临时存储数据的空间,断电后消失

硬盘:持久化数据存储在硬盘当中,文件也是存储在硬盘上的,实际上各大关系型数据库的数据都是存储在文件当中

Mybatis的缓存机制

执行select语句的时候,将查询结果放到缓存当中,如果下一次还是执行完全相同的sql语句,直接从缓存中拿数据,不再查数据,不再去硬盘上拿数据

目的:提高执行效率

缓存机制:减少IO的方式来提高效率

IO:读写文件

缓存通常是我们程序开发中优化程序的重要手段

  • 字符串常量池
  • 整数型常量池
  • 线程池
  • 连接池
Mybatis的缓存

Myabtis的缓存包括

  • 一级缓存:将查询到的数据存储到SqlSession中
  • 二级缓存:将查询到的数据存储到SqlSessionFactory中
  • 或者集成第三方的缓存,EhCache(Java语言开发)
一级缓存

一级缓存默认是开启的,不需要配置,将查询到的数据存储到SqlSession中

当SqlSession不是同一个的时候,不走缓存

一级缓存失效

当第一个DQL语句和第二个DQL语句之间做了两件事中的任意一件都会导致一级缓存失效

  • 执行了sqlSession的clearCache()方法, 手动清空缓存
  • 执行了INSERT或DELETE或UPDATE语句,不管是操作哪张表都会清空一级缓存
二级缓存

使用二级缓存需要配置条件,默认情况下二级缓存是开启的

  • 在核心配置文件中配置<settingname="cacheEnabled" value="true">,默认是true,不用配置
  • 在需要用到二级缓存的sql映射文件中添加配置<cache/>
  • 使用二级缓存的实体类对象必须是可序列化的,必须实现Serializable接口,这样数据就可以以文件的形式存储了
  • SqlSession对象关闭或提交之后,一级缓存中的数据才会被写入二级缓存当中,此时二级缓存才可用

二级缓存的失效

只要二级缓存之间存在INSERT或DELETE或UPDATE语句,不管操作哪个表,二级缓存都会失效

Mybatis的逆向工程

根据数据库逆向生成Java的pojo类,SqlMapper文件以及Mapper接口

QBC风格查询

QBC风格:Query By Criteria 一种查询方式,比较面向对象,看不到sql语句

mybatis的逆向工程的增强版中可以封装查询条件

通过XxxExample对象来封装对象

CarExample carExample = new CarExample();
//调用createCriteria方法来创建查询条件
carExample.createCriteria().andXxxXXX();
//两个查询条件是or的关系
carExample.or().and
Mybatis的PageHelper

页码:pageNum

每页显示的记录条数:pageSize

select *
from t_stu
limit startIndex,pageSize

mysql当中起始行的下标从0开始

在DQL语句之前使用pageHelper完成分页

相关推荐
shabby爱学习2 小时前
matlab 读取csv
数据库·机器学习·matlab
黄名富2 小时前
SQL 语句优化及编程方法
java·数据库·mysql
follycat3 小时前
ISCTF2024
java·网络·数据库·学习·网络安全·python3.11
星星不说话013 小时前
Redis的Zset在排行榜中应用
数据库·redis·缓存
Elastic 中国社区官方博客4 小时前
Elasticsearch:管理和排除 Elasticsearch 内存故障
大数据·运维·数据库·elasticsearch·搜索引擎·全文检索
wh_xia_jun4 小时前
minio数据迁移
数据库
liuxin334455664 小时前
药典新篇:Spring Boot助力中药实验管理
数据库·spring boot·php
WuMingf_5 小时前
Mongodb
数据库·mongodb
永乐春秋5 小时前
WEB攻防-通用漏洞&SQL注入&sqlmap&Oracle&Mongodb&DB2等
sql·mongodb·oracle
MrJson-架构师5 小时前
MongoDB聚合管道数组操作
数据库·mongodb