掌握mybatis3.X的核心流程及增删查改及常见配置,复杂sql和一二级缓存和懒加载

1.Mybatis核心流程

在这里插入图片描述

  • 每个基于Mybatis的应用都是一个SqlSessionFactory的实例为核心
  • SqlSessionFactory的实例可以通过SqlSessionFactoryBulider获得
  • SqlSessionFactoryBuilder可以从XML配置文件或一个预先配置的Configuration实例来构建SqlSessionFactory实例
  • 工厂设计模式里面获取SqlSession,里面提供了在数据库执行SQL命令所需的所有方法。

2.Mybatis3.x快速入门

2.1 添加Maven依赖

<dependencies>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
    <dependency>
       <groupId>org.mybatis</groupId>
       <artifactId>mybatis</artifactId>
       <version>3.5.4</version>
       </dependency>
<!-- 使⽤用JDBC链接mysql的驱动-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.19</version>
    </dependency>
</dependency>

2.2 配置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>
    <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/xdclass?
useUnicode=true&amp;characterEncoding=utf-8&amp;useSSL=false"/>
               <property name="username" value="root"/>
               <property name="password" value="123456"/>
           </dataSource>
      </environment>
</environments>
<mappers>
      <mapper resource="mapper/FistMapper.xml"/>
</mappers>
</configuration>

2.3 配置FistMapper.xml

<?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="net.lcj.dao.FistMapper">
    <select id="selectById"resultType="net.lcj.domain.Video">
     select * from video where id = #{video_id}
    </select>
</mapper>
  • 注:获取java实体中的值时,属性名大小写要一致,并且推荐使用#{value},${value}存在sql注入风险

2.4 通过sqlSession测试一下

public static void main(String [] args) throws IOException {
String resouce = "config/mybatis-config.xml";
//读取配置⽂文件
InputStream inputStream = Resources.getResourceAsStream(resouce);
//构建Session⼯工⼚厂
SqlSessionFactory sqlSessionFactory = new
SqlSessionFactoryBuilder().build(inputStream);
//获取Session
try(SqlSession sqlSession = sqlSessionFactory.openSession()){
VideoMapper videoMapper =
sqlSession.getMapper(VideoMapper.class);
Video video = videoMapper.selectById(44);
//System.out.println(video.toString());
List<Video> videoList = videoMapper.selectList();
System.out.println(videoList.toString());
}
}

2.5 Mybatis使用流程总结一下

  • 创建mybatis-config.xml全局的配置文件
  • 创建XXXMaper.xml配置文件
  • 创建SqlSessionFactory
  • 用SqlSessionFactory创建SqlSession对象
  • 用SqlSession.getMapper获取Mapper接口进行crud操作。

3.MyBatis3.X玩转查询和新增操作

3.1 查询操作及单个参数别名使用

单个参数别名可以这样写

Video selectById(@Param("video_id") int videoId);

多个参数模糊查询
例:根据评分和标题模糊查询 注:参数记得取别名,方便识别和使用
Mapper接口如下:

List<Video> selectByPointAndTitleLike(@Param("point") double point,@Param("title" String title);

Xml实现如下:

<select id="selectByPointAndTitleLike" resultType ="net.lcj.domain.Video">
  select * from video where point =#{point} and title like concat('%',#{title},'%')
</select> 

3.2 数据库字段是下划线,java属性是驼峰映射方法

在mybatis-config.xml文件中加配置

<!--下划线⾃自动映射驼峰字段-->
<settings>
    <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

取参数值,具体某个字段的类型时可以加上jdbcType = VARCHAR

  • 常见的数据库类型和java列席对比

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

3.3 Mybatis实战插入语法新增和自增主键

例:新增一条记录

<insert id="add" parameterType="net.xdclass.online_class.domain.Video">
INSERT INTO `video` ( `title`, `summary`, `cover_img`, `price`,`create_time`, `point`)
VALUES
(#{title,jdbcType=VARCHAR},#{summary,jdbcType=VARCHAR},#{coverImg,jdbcType=VARCHAR},#{price,jdbcType=INTEGER},#{createTime,jdbcType=TIMESTAMP},#{point,jdbcType=DOUBLE});
</insert>

例:获取插入的自增主键

<insert id="add" parameterType="net.xdclass.online_class.domain.Video" 
useGeneratedKeys="true" keyProperty="id" keyColumn="id" >

3.4 Mybatis的foreach批量插入语法

  • foreach:用于凭借的内置标签
    foreach包含属性:
    collection:值为要迭代循环的集合类型,入参是List时,属性值为list,入参是Map时,collection属性为map的key值
    item:每一个元素进行迭代时的别名
    index:索引的属性名,在集合数组情况下值为当前索引值
    open:整个循环内容的开头字符串
    close:整个循环内容的结尾字符串
    separator:每次循环的分隔符

例:Mapper接口:

/**
 *批量插入
 */
int addBatch(List<Video> list);
<!--批量量插⼊入-->
<insert id="addBatch"
parameterType="net.xdclass.online_class.domain.Video" 
useGeneratedKeys="true" keyProperty="id" keyColumn="id" >
INSERT INTO `video` ( `title`, `summary`, `cover_img`, `price`,`create_time`, `point`)
VALUES
<foreach collection="list" item="video" separator=",">
(#{video.title,jdbcType=VARCHAR},#{video.summary,jdbcType=VARCHAR},
#{video.coverImg,jdbcType=VARCHAR},#{video.price,jdbcType=INTEGER},
#{video.createTime,jdbcType=TIMESTAMP},#{video.point,jdbcType=DOUBLE})
</foreach>
</insert>

4 Mybatis3.X更新和删除操作

4.1更新操作1

更新一条记录的接口:

int updateVideo(Video video);

更新xml文件方法:此方法会将不涉及的字段更新为null或者默认值

<update id="updateVideo" parameterType="net.xdclass.online_class.domain.Video">
UPDATE video
set
title = #{title,jdbcType=VARCHAR},
summary = #{summary,jdbcType=VARCHAR},
cover_img = #{coverImg,jdbcType=VARCHAR},
price = #{price,jdbcType=INTEGER},
c_id = #{cId,jdbcType=INTEGER},
point = #{point,jdbcType=INTEGER},
learn_base = #{learnBase,jdbcType=VARCHAR},
learn_result = #{learnResult,jdbcType=VARCHAR},
total_episode = #{totalEpisode,jdbcType=INTEGER},
update_time = now()
WHERE
id = #{id}
</update>

4.2 Mybatis3.X动态字段更新之选择性更新标签

4.2.1 if test标签介绍
  • if标签可以判断传入的值来确定查询条件,test指定的是一个OGNL表达式
  • 常见写法
//当前字段符合条件才更更新这个字段的值
<if test='title != null and id == 87 '> title = #{title}, </if>
<if test="title!=null"> title = #{title}, </if>

更新的xml:

<update id="updateVideoSelective"
parameterType="net.xdclass.online_class.domain.Video">
update video
<trim 前缀+:prefix="set" 后缀-:  suffixOverrides=",">
<if test="title != null "> title = #{title,jdbcType=VARCHAR},
</if>
<if test="summary != null "> summary = #
{summary,jdbcType=VARCHAR},</if>
<if test="coverImg != null "> cover_img = #
{coverImg,jdbcType=VARCHAR},</if>
<if test="price != 0 "> price = #{price,jdbcType=INTEGER},
</if>
<if test="createTime !=null "> create_time = #
{createTime,jdbcType=TIMESTAMP},</if>
<!-- 特别注意: ⼀一定要看pojo类⾥里里⾯面的是基本数据类型,还是包装数据类型,只有包装类型的字段才有判断-->
<if test="point != null "> point = #{point,jdbcType=DOUBLE},
</if>
</trim>
where
id = #{id}
</update>

4.3 Mybatis3.X删除语法和转义字符使用

  • 需求:删除某个时间段之后 且金融大于10元的数据
<delete id="deleteByCreateTimeAndPrice" parameterType="java.util.Map">
delete from video where create_time <![CDATA[ > ]]> #{createTime}
and price <![CDATA[ >= ]]> #{price}
</delete

4.3.1为什么要使用转义字符(sql和Mybatis的xml冲突)

  • 大于等于 <![CDATA[ >= ]]>
  • 小于等于 <![CDATA[ <= ]]>

5 Mybatis3.X的复杂sql查询

5.1 Mybatis3.X的sql片段使用

<sql id="base_video_field">
     id,title,summary,cover_img
</sql>
<select id="selectById" parameterType="java.lang.Integer" resultType="Video">
select <include refid="base_video_field"/> from video where
id = # {video_id,jdbcType=INTEGER}
</select>
  <select id="selectListByXML" resultType="Video">
select <include refid="base_video_field"/> from video
</select>

5.2 Mybatis的resultMap详解

5.2.1 resultMap适合场景
  • 需要自定义字段,或者多表查询,一对多等关系,比resultType更强大
  • 适合复杂查询
    自定义字段查询
<resultMap id="VideoResultMap" type="Video">
       <!--
       id 指定查询列列的唯⼀一标示
       column 数据库字段的名称
       property pojo类的名称
       -->
       <id column="id" property="id" jdbcType="INTEGER" />
       
      <result column="video_tile" property="title" jdbcType="VARCHAR" />
      <result column="summary" property="summary" jdbcType="VARCHAR" />
      <result column="cover_img" property="coverImg" jdbcType="VARCHAR" />
</resultMap>
<select id="selectBaseFieldByIdWithResultMap" resultMap="VideoResultMap">
select id , title as video_tile, summary, cover_img from video where id = #
{video_id}
</select>
5.2.2 resultMap复杂结果一对一查询结果映射association
  • association:映射到POJO的某个复杂类型属性,比如订单order对象里面包含user对象
    例:xml如下:
<resultMap id="VideoOrderResultMap" type="VideoOrder">
     <id column="id" property="id"/>
     <result column="user_id" property="userId"/>
     <result column="out_trade_no" property="outTradeNo"/>
     <result column="create_time" property="createTime"/>
     <result column="state" property="state"/>
     <result column="total_fee" property="totalFee"/>
     <result column="video_id" property="videoId"/>
     <result column="video_title" property="videoTitle"/>
     <result column="video_img" property="videoImg"/>
     <!--
     association 配置属性⼀一对⼀一
     property 对应videoOrder⾥里里⾯面的user属性名
     javaType 这个属性的类型
     -->
    <association property="user" javaType="User">
          <id property="id" column="user_id"/>
          <result property="name" column="name"/>
          <result property="headImg" column="head_img"/>
          <result property="createTime" column="create_time"/>
          <result property="phone" column="phone"/>
    </association>
</resultMap>

<!--⼀一对⼀一管理理查询订单, 订单内部包含⽤用户属性-->
<select id="queryVideoOrderList" resultMap="VideoOrderResultMap">

select
o.id id,
o.user_id ,
o.out_trade_no,
o.create_time,
o.state,
o.total_fee,
o.video_id,
o.video_title,
o.video_img,
u.name,
u.head_img,
u.create_time,
u.phone
from video_order o left join user u on o.user_id = u.id

</select>
5.2.2 resultMap复杂结果一对多查询结果映射collection
  • collection:一对多查询结果映射,比如user有多个订单
    例:xml如下:
<resultMap id="UserOrderResultMap" type="User">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="headImg" column="head_img"/>
<result property="createTime" column="create_time"/>
<result property="phone" column="phone"/>
     <!--
     property 填写pojo类中集合类属性的名称
     ofType 集合⾥里里⾯面的pojo对象
     -->
   <collection property="videoOrderList" ofType="VideoOrder">
   
        <!--配置主键,管理理order的唯⼀一标识-->
        <id column="order_id" property="id"/>
        <result column="user_id" property="userId"/>
        <result column="out_trade_no" property="outTradeNo"/>
        <result column="create_time" property="createTime"/>
        <result column="state" property="state"/>
        <result column="total_fee" property="totalFee"/>
        <result column="video_id" property="videoId"/>
        <result column="video_title" property="videoTitle"/>
        <result column="video_img" property="videoImg"/>
    </collection>
</resultMap>
<select id="queryUserOrder" resultMap="UserOrderResultMap">
select
u.id,
u.name,
u.head_img,
u.create_time,
u.phone,
o.id order_id,
o.out_trade_no,
o.user_id,
o.create_time,
o.state,
o.total_fee,
o.video_id,
o.video_title,
o.video_img
from user u left join video_order o on u.id = o.user_id
</select>

5.3 ResultMap的复杂对象查询总结

  • association 映射的是⼀一个pojo类,处理理⼀一对⼀一的关联关系
  • collection 映射的⼀一个集合列列表,处理理的是⼀一对多的关联关系
  • 模板
<!-- column不不做限制,可以为任意表的字段,⽽而property须为type 定义的pojo属性-->
<resultMap id="唯⼀一的标识" type="映射的pojo对象">
   <id column="表的主键字段,或查询语句句中的别名字段" jdbcType="字段类型" property="映射
   pojo对象的主键属性" />
   <result column="表的⼀一个字段" jdbcType="字段类型" property="映射到pojo对象的⼀一个属
   性"/>
   <association property="pojo的⼀一个对象属性" javaType="pojo关联的pojo对象">
    <id column="关联pojo对象对应表的主键字段" jdbcType="字段类型" property="关联pojo
    对象的属性"/>
    <result column="表的字段" jdbcType="字段类型" property="关联pojo对象的属性"/>
   </association>
   <!-- 集合中的property 需要为oftype定义的pojo对象的属性-->
   <collection property="pojo的集合属性名称" ofType="集合中单个的pojo对象类型">
   <id column="集合中pojo对象对应在表的主键字段" jdbcType="字段类型" property="集合
    中pojo对象的主键属性" />
    <result column="任意表的字段" jdbcType="字段类型" property="集合中的pojo对象的属性" />
  </collection>
</resultMap>

6 Mybatis3.X多级缓存和懒加载

6.1 一级缓存

  • 什么是缓存:程序经常要调⽤用的对象存在内存中,方便其使⽤用时可以快速调⽤用,不不必去数据库或者其他持久化设备中查询,主要就是提⾼高性能
  • Mybatis一级缓存:⼀一级缓存的作⽤用域是SQLSession,同⼀一个SqlSession中执⾏行行相同的SQL查询(相同的SQL和参数),第一次会去查询数据库并写在缓存中,第二次会直接从缓存中取,基于PerpetualCache 的 HashMap本地缓存,默认开启⼀一级缓存。
  • 失效策略:执⾏行行SQL时候两次查询中间发⽣生了了增删改的操作,即insert、 update、 delete等操作commit后会清空该SQLSession缓存; ⽐比如sqlsession关闭,或者清空等

6.2 二级缓存

  • 简介:二级缓存是namespace级别的,多个SqlSession去操作同⼀一个namespace下的Mapper的sql语句句,多个SqlSession可以共⽤用二级缓存,如果两个mapper的namespace相 同,(即使是两个mapper,那么这两个mapper中执⾏行行sql查询到的数据也将存在相同的二级缓存区域中,但是最后是每个Mapper单独的名称空间),默认是没有开启⼆二级缓存,操作流程:第⼀一次调⽤用某个namespace下的SQL去查询信息,查询到的信息会存放该mapper对应的二级缓存区域。第二次调⽤用同个namespace下的mapper映射⽂文件中,相同的sql去查询信息,会去对应的二级缓存内取结果
  • 失效策略略:执⾏行行同个namespace下的mapepr映射⽂文件中增删改sql,并执⾏行行了了commit操作,会清空该⼆二级缓存
  • 注意:实现二级缓存的时候, MyBatis建议返回的POJO是可序列列化的, 也就是建议实Serializable接口
  • 缓存淘汰策略略:会使⽤用默认的 LRU 算法来收回(最近最少使⽤用的)
  • 如何开启某个⼆二级缓存 mapper.xml⾥里里⾯面配置
<!--开启mapper的namespace下的⼆二级缓存-->
<!--
eviction:代表的是缓存回收策略略,常⻅见下⾯面两种。
(1) LRU,最近最少使⽤用的,⼀一处最⻓长时间不不⽤用的对象
(2) FIFO,先进先出,按对象进⼊入缓存的顺序来移除他们
flushInterval:刷新间隔时间,单位为毫秒,这⾥里里配置的是100秒刷新,如果不不配置
它,当SQL被执⾏行行的时候才会去刷新缓存。
size:引⽤用数⽬目,代表缓存最多可以存储多少个对象,设置过⼤大会导致内存溢出
readOnly:只读,缓存数据只能读取⽽而不不能修改,默认值是false
-->
<cache eviction="LRU" flushInterval="100000" readOnly="true" size="1024"/>
全局配置:
<settings>
<!--这个配置使全局的映射器器(⼆二级缓存)启⽤用或禁⽤用缓存,全局总开关,这⾥里里关闭, mapper中开启
了了也没⽤用-->
<setting name="cacheEnabled" value="true" />
</settings>
  • 一级缓存和二级缓存使⽤用顺序
  • 优先查询二级缓存-》查询一级缓存-》数据库
  • 某个方法不使用二级缓存
<select id="selectById" parameterType="java.lang.Integer"
resultType="Video" useCache="false">
select <include refid="base_video_field"/> from video where id = #
{video_id,jdbcType=INTEGER}
</select>

6.3 Mybatis懒加载

  • 什么是懒加载:按需加载,先从单表查询,需要时再从关联表去关联查询,能⼤大提高数据库性能,并不是所有场景下使用懒加载都能提高效率
  • Mybatis懒加载: resultMap里⾯的association、 collection有延迟加载功能
    在Mybatis-config.xml中添加配置
<!--全局参数设置-->
<settings>
<!--延迟加载总开关-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--将aggressiveLazyLoading设置为false表示按需加载,默认为true-->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
<resultMap id="VideoOrderResultMapLazy" type="VideoOrder">
<id column="id" property="id"/>
<result column="user_id" property="userId"/>
<result column="out_trade_no" property="outTradeNo"/>
<result column="create_time" property="createTime"/>
<result column="state" property="state"/>
<result column="total_fee" property="totalFee"/>
<result column="video_id" property="videoId"/>
<result column="video_title" property="videoTitle"/>
<result column="video_img" property="videoImg"/>
<!--
select: 指定延迟加载需要执⾏行行的statement id
column: 和select查询关联的字段
-->
<association property="user" javaType="User" column="user_id"
select="findUserByUserId"/>
</resultMap>
<!--⼀一对⼀一管理理查询订单, 订单内部包含⽤用户属性 懒加载-->
<select id="queryVideoOrderListLazy" resultMap="VideoOrderResultMapLazy">
select
o.id id,
o.user_id ,
o.out_trade_no,
o.create_time,
o.state,
o.total_fee,
o.video_id,
o.video_title,
o.video_img
from video_order o
</select>
<select id="findUserByUserId" resultType="User">
select * from user where id=#{id}
</select>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值