Java面试之Mybatis

在这里插入图片描述

1.工作原理

在这里插入图片描述

(1)SqlSessionFactoryBuilder().build(inputStream):这行代码解析mybatis.xml文件,解析mapper节点。mapper也就是我们定义的如UserMapper.xml这种文件,将其解析成一个mapperStatement中,然后存放在Configraution这个对象中,这个对象又是sqlSessionFactory中的一个属性。(2)sqlSessionFactory.openSession():开启一个会话,用来执行sql。
(3)sqlSession.getMapper(UserDao.class):jdk动态代理生成UserDao接口的实现对象。执行对应的方法。

  1. 加载mybatis全局配置文件(数据源、mapper映射文件等),解析配置文件,MyBatis基于XML配置文件生成Configuration,和一个个MappedStatement(包括了参数映射配置、动态SQL语句、结果映射配置),其对应着<select | update | delete | insert>标签项。

  2. SqlSessionFactoryBuilder通过Configuration对象生成SqlSessionFactory,用来开启SqlSession。

  3. SqlSession对象完成和数据库的交互:
    a、用户程序调用mybatis接口层api(即Mapper接口中的方法)
    b、SqlSession通过调用api的Statement ID找到对应的MappedStatement对象
    c、通过Executor(负责动态SQL的生成和查询缓存的维护)将MappedStatement对象进行解析,sql参数转化、动态sql拼接,生成jdbc Statement对象
    d、JDBC执行sql。
    e、借助MappedStatement中的结果映射关系,将返回结果转化成HashMap、JavaBean等存储结构并返回。

2.mybatis缓存问题

一级缓存,每次进行执行sql语句的时候,会创建一个sqlSession。但可能这个sqlSession会执行多条相同的语句,为了减轻mysql的压力,就在sqlSession使用map来做缓存。每次查询的时候,会判断是否存在一个完全一样的查询,如果存在,就直接走换存。一级缓存是默认打开的。在insert、update、delete的时候,会清空所有的数据。一级缓存默认开启,无法关闭。但有两个级别可以选择。但以及查询有个缺陷,就是缓存只在会话中共享,如果不同的会话进行查询或者修改,可能会造成数据不一致的情况。解决办法是设置为statement级别,每次都会清空缓存。mybatis一级缓存的命中条件(1)同一个类同一个方法同一个参数构成的可以key; (2)同一个sqlSession中才能命中。
在这里插入图片描述
一级缓存中,其最大的共享范围就是一个SqlSession内部,如果多个SqlSession之间需要共享缓存,则需要使用到二级缓存。开启二级缓存后,会使用CachingExecutor装饰Executor,进入一级缓存的查询流程前,先在CachingExecutor进行二级缓存的查询,具体的工作流程如下所示。

二级缓存开启后,同一个namespace下的所有操作语句,都影响着同一个Cache,即二级缓存被多个SqlSession共享,是一个全局的变量。

当开启缓存后,数据的查询执行的流程就是 二级缓存 -> 一级缓存 -> 数据库。

  1. MyBatis的二级缓存相对于一级缓存来说,实现了SqlSession之间缓存数据的共享,同时粒度更加的细,能够到namespace级别,通过Cache接口实现类不同的组合,对Cache的可控性也更强。

  2. MyBatis在多表查询时,极大可能会出现脏数据,有设计上的缺陷,安全使用二级缓存的条件比较苛刻。

  3. 在分布式环境下,由于默认的MyBatis Cache实现都是基于本地的,分布式环境下必然会出现读取到脏数据,需要使用集中式缓存将MyBatis的Cache接口实现,有一定的开发成本,直接使用Redis,Memcached等分布式缓存可能成本更低,安全性也更高。

3.mybatis 如何防止 sql 注入?$和#的区别是什么?传入表名用哪个?

防止 sql 注入:
在编写 mybatis 的映射语句时,尽量采用“#{xxx}”这样的格式
在这里插入图片描述
简单的说就是#{}是经过预编译的,是安全的,${}是未经过预编译的,仅仅是
取变量的值,是非安全的,存在 SQL 注入。
要实现动态传入表名、列名,需要做如下修改:
添加属性 statementType=“STATEMENT”,同时 sql 里的属有变量取值都改成 ${xxxx}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值