mybatis回顾

一、默认配置

1.环境配置

尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。
mybatis默认的事务管理器就是JDBC,,默认的连接池:POOLED

2.配置文件有顺序

The content of element type “configuration” must match “(properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,objectWrapperFactory?,reflectorFactory?,plugins?,environments?,databaseIdProvider?,mappers?)”.

3.settings

常见的设置: cacheEnabled ,lazyLoadingEnabled ,logImpl
详见:https://mybatis.org/mybatis-3/zh/configuration.html

4.映射器

注意点:
1.接口和他的Mapper配置文件同名!
2.接口和他的Mapper配置文件必须在同一个包下!

二、生命周期和作用域

理解我们之前讨论过的不同作用域和生命周期类别是至关重要的,因为错误的使用会导致非常严重的并发问题。

在这里插入图片描述

1. SqlSessionFactoryBuilder

a.一旦创建SqlSessionFactoryBuilder,就不在需要
b.局部变量

2. SqlSessionFactory

a.说白了,可以想象成:数据库连接池
b.SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例
c.SqlSessionFactory 的最佳作用域是应用作用域
d.最简单的就是使用单例模式或者静态单例模式。

3. SqlSession

在这里插入图片描述

a.连接到连接池的一个请求
b.SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。
c.用完之后,需要赶紧关闭,否则占用资源!

在这里插入图片描述

三、解决属性名和字段名不一致的问题

1.起别名
2.resultMap

四、分页

在这里插入图片描述

五、注解开发

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

六、复杂查询

1. 多对一

A、按照结果嵌套处理

在这里插入图片描述

B、按照查询嵌套处理

在这里插入图片描述

2. 一对多

A、按照结果嵌套查询

在这里插入图片描述

B、按照查询嵌套方式处理

在这里插入图片描述

3.小结

在这里插入图片描述

4.面试高频

mysql 引擎
innoDB底层
索引
索引优化

七、动态sql

在这里插入图片描述

八 、缓存

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

1.一级缓存

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

2.二级缓存

在这里插入图片描述

如何开启二级缓存:
在这里插入图片描述

在这里插入图片描述

    /**
     * 一级缓存
     * 特性:
     * 1.默认就开启了,也可以关闭一级缓存 localCacheScope=STATEMENT
     * 2.作用域:是基于sqlSession(默认),一次数据库操作会话。
     * 3.缓存默认实现类PerpetualCache ,使用map进行存储的
     * 4.查询完就会进行存储
     * 5.先从二级缓存中获取,再从一级缓存中获取
     * key==>   sqlid+sql
     * 失效情况:
     * 1.不同的sqlSession会使一级缓存失效
     * 2.同一个SqlSession,但是查询语句不一样
     * 3.同一个SqlSession,查询语句一样,期间执行增删改操作
     * 4.同一个SqlSession,查询语句一样,执行手动清除缓存
     */
     /**
     * 二级缓存:
     *    特性:
     *      1.默认开启了,没有实现
     *      2.作用域:基于全局范围,应用级别。
     *      3.缓存默认实现类PerpetualCache ,使用map进行存储的但是二级缓存根据不同的mapper命名空间多包了一层map
     *              : org.apache.ibatis.session.Configuration#caches    key:mapper命名空间   value:erpetualCache.map
     *          * key==> sqlid+sql
     *      4.事务提交的时候(sqlSession关闭)
     *      5.先从二级缓存中获取,再从一级缓存中获取
     *   实现:
     *      1.开启二级缓存<setting name="cacheEnabled" value="true"/>
     *      2.在需要使用到二级缓存的映射文件中加入<cache></cache>,基于Mapper映射文件来实现缓存的,基于Mapper映射文件的命名空间来存储的
     *      3.在需要使用到二级缓存的javaBean中实现序列化接口implements Serializable
     *          配置成功就会出现缓存命中率 同一个sqlId: 从缓存中拿出的次数/查询总次数
     *
     *   失效:
     *      1.同一个命名空间进行了增删改的操作,会导致二级缓存失效
     *          但是如果不想失效:可以将SQL的flushCache 这是为false,但是要慎重设置,因为会造成数据脏读问题,除非你能保证查询的数据永远不会执行增删改
     *      2.让查询不缓存数据到二级缓存中useCache="false"
     *      3.如果希望其他mapper映射文件的命名空间执行了增删改清空另外的命名空间就可以设置:
     *          <cache-ref namespace="cn.tulingxueyuan.mapper.DeptMapper"/>
     *
     */

3、缓存原理

在这里插入图片描述

八、框架流程图

在这里插入图片描述

九、实例(嵌套查询)

<?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="cn.tulingxueyuan.mapper.DeptMapper">

    <!-- 根据部门id查询部门-->
    <select id="SelectDept" resultType="dept">
        SELECT * FROM dept where id=#{id}
    </select>

    <!-- 嵌套结果: 一对多  查询部门及所有员工 -->
    <resultMap id="SelectDeptAndEmpsMap" type="Dept">
        <id column="d_id"  property="id"></id>
        <id column="dept_name"  property="deptName"></id>
        <!--
        <collection  映射一对多中的 “多”
            property 指定需要映射的“多”的属性,一般声明为List
            ofType  需要指定list的类型
        -->
        <collection property="emps" ofType="Emp" >
            <id column="e_id" property="id"></id>
            <result column="user_name" property="username"></result>
            <result column="create_date" property="createDate"></result>
        </collection>
    </resultMap>

    <select id="SelectDeptAndEmps" resultMap="SelectDeptAndEmpsMap">
        select t1.id as d_id,t1.dept_name,t2.id e_id,t2.user_name,t2.create_date from dept t1
        LEFT JOIN emp t2 on t1.id=t2.dept_id
        where t1.id=#{id}
    </select>


    <!-- 嵌套查询(异步查询): 一对多  查询部门及所有员工 -->
    <resultMap id="SelectDeptAndEmpsMap2" type="Dept">
        <id column="d_id"  property="id"></id>
        <id column="dept_name"  property="deptName"></id>
        <!--
        <collection  映射一对多中的 “多”
            property 指定需要映射的“多”的属性,一般声明为List
            ofType  需要指定list的类型
            column 需要将当前查询的字段传递到异步查询的参数
            select 指定异步查询
        -->
        <collection property="emps" ofType="Emp" column="id" select="cn.tulingxueyuan.mapper.EmpMapper.SelectEmpByDeptId" >
        </collection>
    </resultMap>

    <select id="SelectDeptAndEmps2" resultMap="SelectDeptAndEmpsMap2">
        SELECT * FROM dept where id=#{id}
    </select>
</mapper>
<?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="cn.tulingxueyuan.mapper.EmpMapper">


    <!-- 实现表联结查询的方式:  可以映射map 或者 DTO -->
    <resultMap id="QueryEmp_Map" type="QueryEmpDTO">
        <id column="e_id" property="id"></id>
        <result column="user_name" property="username"></result>
        <result column="d_id" property="deptId"></result>
        <result column="dept_name" property="deptName"></result>
    </resultMap>

    <select id="QueryEmp"  resultMap="QueryEmp_Map">
        select t1.id as e_id,t1.user_name,t2.id as d_id,t2.dept_name from emp t1
        INNER JOIN dept t2 on t1.dept_id=t2.id
        where t1.id=#{id}
    </select>


    <!--嵌套结果   多 对 一  -->
    <resultMap id="QueryEmp_Map2" type="Emp">
        <id column="e_id" property="id"></id>
        <result column="user_name" property="username"></result>
        <!--
        association 实现多对一中的  “一”
            property 指定对象中的嵌套对象属性
        -->
        <association property="dept">
            <id column="d_id" property="id"></id>
            <id column="dept_name" property="deptName"></id>
        </association>
    </resultMap>

    <select id="QueryEmp2"  resultMap="QueryEmp_Map2">
        select t1.id as e_id,t1.user_name,t2.id as d_id,t2.dept_name from emp t1
        INNER JOIN dept t2 on t1.dept_id=t2.id
        where t1.id=#{id}
    </select>

    <!--嵌套查询(分步查询)   多 对 一
      联合查询和分步查询区别:   性能区别不大
                                分部查询支持 懒加载(延迟加载)
       需要设置懒加载,一定要使用嵌套查询的。
       要启动懒加载可以在全局配置文件中设置 lazyLoadingEnabled=true
       还可以单独为某个分步查询设置立即加载 <association fetchType="eager"
      -->
    <resultMap id="QueryEmp_Map3" type="Emp">
        <id column="id" property="id"></id>
        <result column="user_name" property="username"></result>
        <!-- association 实现多对一中的  “一”
            property 指定对象中的嵌套对象属性
            column  指定将哪个字段传到分步查询中
            select 指定分步查询的 命名空间+ID
            以上3个属性是实现分步查询必须的属性
            fetchType 可选, eager|lazy   eager立即加载   lazy跟随全局配置文件中的lazyLoadingEnabled
         -->
        <association property="dept" fetchType="eager"  column="dept_id"  select="cn.tulingxueyuan.mapper.DeptMapper.SelectDept">
        </association>
    </resultMap>

    <select id="QueryEmp3"  resultMap="QueryEmp_Map3">
       select  * from emp where id=#{id}
    </select>


    <!-- 根据部门id所有员工 -->
    <select id="SelectEmpByDeptId"  resultType="emp">
        select  * from emp where dept_id=#{id}
    </select>

</mapper>

十、动态SQL

<?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="cn.tulingxueyuan.mapper.EmpMapper">

    <!-- 查询Emp 根据id,username ,创建的开始时间和结束时间,根据部门id
    如果在编写SQL过程中出现特殊字符报错: 1.进行转义
                                         2.使用cdata <![CDATA[<=]]>
    -->
    <!--
    使用动态SQL:
    1.实现动态条件SQL
    <if
           test 条件表达式 支持OGNL表达式
      问题: and 需要动态拼接的问题(只有一个条件的情况就不需要and,如果多个条件就必须用and/or 来拼接)
           解决:1.加一个永远都成立的条件(比如:1=1) , 后面条件都加上and/or就行
                 2.<where
                 3.<trim
    <where 一般会加载动态条件中配合使用, 在有条件的情况下它会自动在所有条件的前面加上WHERE关键字, 还会去掉所有条件前面的AND/OR
    <trim  它的功能比较灵活、广泛。 它可以用来实现<where节点的功能
        prefix 在所有包含的SQL前面加上指定的字符串
       prefixOverrides  在所有包含的SQL前面加上去除指定的字符串
       suffix 在所有包含的SQL后面加上指定的字符串
       prefixOverrides  在所有包含的SQL后面加上去除指定的字符串

    -->
    <select id="QueryEmp" resultType="Emp">
        <include refid="SelectEmp">
            <property name="tableName" value="emp"/>
        </include>
        <trim prefix="WHERE" prefixOverrides="and|or"  >
            <if test="id!=null and id>0 ">
                and  id=#{id}
            </if>
            <!--OGNL调用对象的方法-->
            <if test="username!=null and username.indexOf('')>-1 ">
                and user_name=#{username}
            </if>
            <if test="beginDate!=null">
                and create_date >=#{beginDate}
            </if>
            <if test="endDate!=null">
                and create_date <![CDATA[<=]]> #{endDate}
            </if>
            <!--OGNL: gt 是大于
                调用静态方法 -->
            <if test="deptId!=null and deptId gt @cn.tulingxueyuan.pojo.Emp@getNum() ">
                and dept_id=#{deptId}
            </if>
        </trim>

        <!--<where>
            <if test="id!=null and id!='' ">
                and  id=#{id}
            </if>
            <if test="username!=null and username!='' ">
              and user_name=#{username}
            </if>
            <if test="beginDate!=null and beginDate!='' ">
              and create_date >=#{beginDate}
            </if>
            <if test="endDate!=null and endDate!='' ">
              and create_date <![CDATA[<=]]> #{endDate}
            </if>
            <if test="deptId!=null and deptId!='' ">
              and dept_id=#{deptId}
            </if>
        </where>-->
    </select>


    <!--
    <choose when otherwise
    多条件取其中一个
    -->
    <select id="QueryEmp2" resultType="Emp">
        <include refid="SelectEmp">
            <property name="columns" value="id,dept_id"/>
        </include>
        <where>
            <choose>
                <when test="deptName=='经理'">
                    dept_id=1
                </when>
                <when test="deptName=='普通员工'">
                    dept_id=2
                </when>
                <otherwise>
                    dept_id=#{id}
                </otherwise>
            </choose>

        </where>
    </select>

    <!--
    <foreach  循环
        实现in 范围查询  使用$可以实现但是有sql注入风险
       collection 需要循环的集合的参数名字
        item  每次循环使用的接收变量
        separator 分割符设置(每次循环在结尾添加什么分隔符,会自动去除最后一个结尾的分隔符)
        open 循环开始添加的字符串
        close 循环结束添加的字符串
        index 循环的下标的变量
    -->
    <select id="QueryEmp3" resultType="Emp">
        <include refid="SelectEmp">
            <property name="columns" value="id,user_name,dept_id"/>
        </include>
        <where>
            <foreach collection="usernames" item="username" separator="," open=" user_name in (" close=")" index="i" >
                #{username}
            </foreach>
        </where>
    </select>

    <!--
    <set 用在update语句上面的
        会自动加上set关键字
        会自动去除最后一个更新字段的,
    -->
    <update id="update">
        update emp
        <!--<trim prefix="set" suffixOverrides=",">
            <if test="username!=null and username!='' ">
            user_name=#{username},
            </if>
            <if test="createDate!=null and createDate!='' ">
            create_date=#{createDate},
            </if>
            <if test="deptId!=null and deptId!='' ">
            dept_id=#{deptId}
            </if>
        </trim>-->
        <set>
            <if test="username!=null and username!='' ">
                user_name=#{username},
            </if>
            <if test="createDate!=null">
                create_date=#{createDate},
            </if>
            <if test="deptId!=null and deptId!='' ">
                dept_id=#{deptId},
            </if>
        </set>
        where  id=#{id}
    </update>


<!-- 实现模糊查询 like '%xx%'
1可以使用mysql的字符串拼接   1. 空格拼接  2.CONCAT函数
2可以拼接好再传进来
3使用bind在Mapper映射文件上下文声明一个变量 <bind>
-->
<!--
 <bind> 在Mapper映射文件上下文声明一个变量
    name 变量名称
    value 值(支持OGNL表达式)
-->

<!--
sql片段  解决SQL中重复的代码冗余,可以提取出来放在sql片段中
    1.  <sql 定义sql片段
            id 唯一标识
    2.   <include 在SQL中引用SQL片段片段
            refid 需要引用的SQL片段的id
            <property 声明变量, 就可以在SQL片段中动态调用,让不同的SQL调用同一个SQL片段达到不同的功能
                name 变量名
                value 变量值
                一般情况使用${}在sql片段中引用.一单引用了,一定保证每个include都声明了该变量
-->
    <select id="QueryEmp4" resultType="Emp">
        <bind name="_username" value="'%'+username+'%' "/>
        <include refid="SelectEmp">
            <property name="columns" value="id"/>
        </include> 
        where user_name like    #{_username}
    </select>
    
    <sql id="SelectEmp">
        SELECT ${columns} FROM emp
    </sql>

    <!--循环逐条插入-->
    <insert id="insert">
        insert into emp (user_name,create_date,dept_id)
            values (#{username},#{createDate},#{deptId})
    </insert>
    <!--循环逐条插入-->
    <insert id="inserBatch">
        insert into emp (user_name,create_date,dept_id)
        values
        <foreach collection="emps" item="emp" separator=",">
        (#{emp.username},#{emp.createDate},#{emp.deptId})
        </foreach>
    </insert>


    <!--循环逐条插入-->
    <insert id="inserBatch">
        insert into emp (user_name,create_date,dept_id)
        values
        <foreach collection="emps" item="emp" separator=",">
            (#{emp.username},#{emp.createDate},#{emp.deptId})
        </foreach>
    </insert>

</mapper>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值