mybatis的工作原理
mybatis是一个数据持久层框架,它封装了jdbc,简化了对数据库增删改查的操作,简化了参数和结果集映射过程,让开发人员只需关注SQL本身。
工作原理:
1、加载配置:配置来源于两个地方,一处是配置文件,一处是Java代码的注解,将SQL配置信息加载成为一个MappedStatement对象(包括了传入参数映射配置,执行的SQL语句、结果映射配置),存储在内存中。
2、SQL解析:当API接口层收到请求调用时,会接受到传入SQL的id和传入对象(可以是Map、JavaBean、或者基本数据类型),Mybatis会根据SQL的id找到对应的MappedStatement,然后根据传入参数对象对MappedStatement进行解析,解析后可以得到最终要执行的SQL语句和参数。
3、SQL执行:将最终得到的SQL和参数拿到数据库进行执行,得到操作数据库的结果。
4、结果映射:将操作数据库的结果按照映射的配置进行转换,可以装换成hashMap、JavaBean或者基本数据类型,并将最终结果返回。
使用经验
Mbatis 适用于需要对SQL完全控制的场合,通常这么做可以对SQL进行进一步优化,可以获得更好的性能。
Mybatis自带的分页实现时逻辑分页,只适用于数据量非常少的情况,更多情况下应该使用自己的物理分页SQL取代它。
Mybatis中#{} 和${} 的区别
1、#{}和${}工作原理
假设有如下Java实体对象
public class City{
private int id;
private String name;
}
1)#{}
用于生成PreparedStatement 方式的占位参数,mapper文件编写如下
<insert id="insert" parameterType="entity.City"> insert into city(id,name) values(#{id},#{name}) </insert>
最后执行时会生成如下的等价jdbc代码
PreparedStatement stmt=conn.prepareStatement("insert into city(id,name) values(?,?)");
stmt.setInt(1,id值);
stmt.setString(2,name值);
stmt.executeUpdate()
2)${}
是采用拼接字符串方式生成SQL语句,不会利用占位参数的方式,mapper文件编写如下
<insert id="insert" parameterType="entity.City"> insert into city(id,name) values(${id},${name}) </insert>
最后执行时会生成如下的等价jdbc代码
PreparedStatement stmt=conn.prepareStatement("insert into city(id,name) values(id值,'name值')");
stmt.executeUpdate()
2它们的区别
由以上工作原理可知
${}的安全性较差,可能会导致SQL注入攻击;#{}相对安全
#{} 只能替换SQL语句中的 值部分,不能替换表名、列名;而${}可以替换SQL与语句的任意部分
#{}內不能含有表达式,不能进行运算;而${}内可以使用ognl语法进行简单运算。
Mybatis中的缓存
缓存主要的目的是提高查询查询效率,减轻数据库的访问压力。mybatis中的缓存分为一级缓存与二级缓存
一级缓存是每个SqlSession自带的,无需额外的配置,在SQLSession打开一级缓存就会创建,第一次查询的结果会存入一级缓存,后续只要执行了相同的SQL,那么会从缓存中获取上次的结果,而不必查询数据库,从而提高了效率。当SQLSession关闭时,一级缓存也会清空。不通的SqlSession之间不能共享一级缓存的结果。
二级缓存从功能上与一级缓存类似,不同在于二级缓存的数据可以在多个SQLSession中共享,SqlSession查询的结果会存入二级缓存,只要执行的SQL相同,SQLSession2 也可以从二级缓存中获取该结果。二级缓存需要在映射文件中添加<cache>
标签来进行配置。
Mybatis中二级缓存是一个Mapper 对应一个二级缓存,此Mapper中的查询,会将结果存入二级缓存,但同一Mapper中的增删改,会清空二级缓存(为了防止脏数据)。从这个角度讲,只有数据不频繁修改时,才适合使用二级缓存。