Mybatis面经

Mybatis

📑前言

本文主要是【Mybatis】------Mybatis面经的文章,如果有什么需要改进的地方还请大佬指出⛺️

🎬作者简介:大家好,我是听风与他🥇

☁️博客首页:CSDN主页听风与他

🌄每日一句:狠狠沉淀,顶峰相见

目录

1.缓存

  • mybatis对缓存提供支持,一级缓存是默认使用的,二级缓存需要手动开启。

区别:

  • 一级缓存的作用域是一个sqlsession内;
  • 二级缓存作用域是针对mapper进行缓存;

1.1一级缓存

  • 在参数和SQL完全一样的情况下,我们使用同一个SqlSession对象调用一个Mapper方法,往往只执行一次SQL,因为使用SqlSession第一次查询后,Mybatis会将其放在缓存中,以后再查询的时候,如果没有声明需要刷新,并且缓存没有超时的情况下,SqlSession都会取出当前缓存的数据,而不会再次发送SQL到数据库。
  • 一级缓存执行commit,close,增删改等操作,就会清空当前的一级缓存,当对SqlSession执行更新操作(update,delete,insert)后执行commit时,不仅清空自身的一级缓存(执行更新操作的效果),也清空二级缓存(执行commit()的效果)

1.3二级缓存

  • 二级缓存指的是同一个namespace下的mapper,二级缓存中,也有一个map结构,这个区域就是一级缓存区域。一级缓存中的key是由sql语句,条件,statement等信息组成一个唯一值,一级缓存中的value,就是查询出的结果对象。

1.4在配置文件中,开启二级缓存的总开关

xml 复制代码
<setting name="cacheEnabled" value="true" />

2.在mapper映射文件中开启二级缓存

xml 复制代码
<cache eviction="FIFO" flushInterval="60000" size="512" 
readOnly="true"/>

禁用缓存

xml 复制代码
<select id="findAllPets" resultMap="petsMap" useCache="false">
 select * from pets
</select>

刷新缓存

  • 在印射文件中,属性: flushCache='true'刷新缓存,在查询语句中,默认值是falsh,在新增删除修改语句中,默认值是true(清空缓存)

2.mybatis是半自动ORM映射工具,它与全自动的区别?

  • hibernate属于全自动ORM映射工具,使用hibernate查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。而mybatis在查询关联对象或关联集合对象时,需要手动编写sql来完成,所以,称为半自动ORM映射工具。

3.Mybatis和Hibernate有哪些不同?

  • Mybatis和Hibernate不同,它不完全是一个ORM框架,因为Mybatis需要程序员自己编写sql语句,不过mybatis可以通过XML或注解方式灵活配置要运行的sql语句,并将java对象和sql语句映射生成最终执行的sql,最后将sql执行的结果再映射生成java对象。
  • Mybatis学习门槛低,简单易学,程序员直接编写原生态sql,可严格控制sql执行性能,灵活度高,非常适合对关系数据模型要求不高的软件开发,例如互联网软件、企业运营类软件等,因为这类软件需求变化频繁,一旦需求变化要求成果输出迅速。但是灵活的前提是mybatis无法做到数据库无关性,如果需要实现支持多种数据库的软件则需要自定义多套sql映射文件,工作量大。

4.Mybatis中#{ }和${ }的区别

  • 相同点:都能取到变量的值

  • 不同点:#{ }可以实现预编译,会先把#{ }编译成?,在执行时再取值,可以防止sql注入。

  • ${ }是直接进行字符串替换

  • #符号解析:主要在数据类型检查和安全检查两部分。

    • 数据类型检查表现在:若检测到为数值类型,就不加引号,若检测到为字符串类型,就加上引号,即'?'
    • 安全检查表现在:若变量的值带有引号,会对引号进行转义处理,这样可以防止sql注入。
  • #符号的应用场景:需要在sql映射文件中动态拼接sql时的开发场景,比如传入多个变量进行条件查询,传入一个pojo进行数据插入等。

  • 符号解析: { }符号解析: 符号解析:符号主要用于传入的参数是sql片段的场景下,会直接进行字符串替换,完成了sql的拼接,

  • 比如我们不在sql映射文件中利用mybatis的动态sql来拼接sql,而是在java代码中去动态的拼接sql,然后将拼接的sql片段作为变量传入sql映射文件。上面也说了$符号只是进行字符串的替换,如果我们传入一个sql片段的话,相当于直接进行了sql拼接,就不用在sql映射文件中利用mybatis提供的动态sql标签来拼接sql了。甚至可以这样:

    xml 复制代码
    <select id="getUserPage" resultType="com.ymxx.oa.bean.User">
            ${sql片段}
    </select>

    *对于这样外部传入的sql,就不能使用#{},上面也说了,#{}会进行预编译,检测到该sql片段是个字符串,就会加上引号,即'sql片段',这样就是字符串了而不是sql,执行会报错。*

依据$适用于传入sql片段的情况,我们可以将数据表字段名、表名、数据库名等传入,来进行sql拼接,如:

$符号的应用场景:

比如:select ${columns} from ${tableName},假设columns变量的值是userName,age 。tableName变量的值是user,那么该sql语句就会被解析成:select userName,age from user

比如有这样一个需求:对于后台管理系统的table列,想让用户选择展示哪些列,不展示哪些列,或者根据权限来分配不同的用户可以看到哪些列?

这个需求正好用到了 符号,我们可以将每个用户对于一个 t a b l e 能看到哪些列,存储到数据表中,对该数据表进行 c r u d ,每次展示列表的时候,先根据用户 I D 和 t a b l e 类型,到数据表中查询该用户对该 t a b l e 能看到的列名 ( 字段名 ) 列表,然后将该字段名列表作为 s q l 片段传入 m y b a t i s 进行查询,此时就必须得用到 符号,我们可以将每个用户对于一个table能看到哪些列,存储到数据表中,对该数据表进行crud,每次展示列表的时候,先根据用户ID和table类型,到数据表中查询该用户对该table能看到的列名(字段名)列表,然后将该字段名列表作为sql片段传入mybatis进行查询,此时就必须得用到 符号,我们可以将每个用户对于一个table能看到哪些列,存储到数据表中,对该数据表进行crud,每次展示列表的时候,先根据用户ID和table类型,到数据表中查询该用户对该table能看到的列名(字段名)列表,然后将该字段名列表作为sql片段传入mybatis进行查询,此时就必须得用到符号,而不能用#符号了。

符号的 s q l 注入问题:用 符号的sql注入问题: 用 符号的sql注入问题:用{}时要特别注意sql注入的风险,如果该sql片段是根据用户的输入拼接的,要注意检查sql注入的问题,防止数据的泄露与丢失!

5.resultmap与resulttype的区别

  • resultmap与resulttype的区别为:对象不同,描述不同,类型适用不同。
  • 简单来说,就是resultmap和resulttype功能差不多,但是resultmap功能更强大。

resultType:

  • 使用resultType进行输出映射时,至少查询出来的列名和pojo(简单实例对象)中的属性名一致,该列才可以映射成功。

  • int,string,list中元素的类型

    xml 复制代码
       <select id="count" resultType="int">
            select count(id) from t_paper as p
            LEFT JOIN  t_type as t
            ON
            p.type_id=t.id
       </select>

resultMap:

  • resultMap可以实现将查询结果映射为复杂类型的pojo,简单来说就是,resultType解决不了的,都交给resultMap来解决。在使用resultMap之前我们需要先定义一个符合当前需求的resultMap.
xml 复制代码
   <resultMap id="paperResult" type="Paper">
        <!-- column:数据库字段名 property:实体的属(变量)名 -->
        <result column="id" property="id"/> 
        <result column="title" property="title"/>
        <result column="type_id" property="typeId"/>
        <result column="paper_summary" property="paperSummary"/>
        <result column="paper_path" property="paperPath"/>
    </resultMap>
 
 
    <select id="selectPaperListByCondition" resultMap="paperResult">
           SELECT
              p.*, t.type_name from t_paper as p
           LEFT JOIN
              t_type as t
           ON
              p.type_id=t.id
           WHERE
              title='' and type_name=''
            <where>
               <if test="title != null and title != ''">
                   and title like '%${title}%'
               </if>
                <if test="typeName != null and typeName != ''">
                    and type_name=#{typeName}
                </if>
            </where>
           limit #{start},#{size}
    </select>

📑文章末尾

相关推荐
wainyz5 分钟前
Java NIO操作
java·开发语言·nio
工业3D_大熊10 分钟前
【虚拟仿真】CEETRON SDK在船舶流体与结构仿真中的应用解读
java·python·科技·信息可视化·c#·制造·虚拟现实
lzb_kkk19 分钟前
【JavaEE】JUC的常见类
java·开发语言·java-ee
爬山算法43 分钟前
Maven(28)如何使用Maven进行依赖解析?
java·maven
2401_857439691 小时前
SpringBoot框架在资产管理中的应用
java·spring boot·后端
怀旧6661 小时前
spring boot 项目配置https服务
java·spring boot·后端·学习·个人开发·1024程序员节
李老头探索1 小时前
Java面试之Java中实现多线程有几种方法
java·开发语言·面试
芒果披萨1 小时前
Filter和Listener
java·filter
qq_4924484461 小时前
Java实现App自动化(Appium Demo)
java
阿华的代码王国1 小时前
【SpringMVC】——Cookie和Session机制
java·后端·spring·cookie·session·会话