Mybatis基本流程

1 读取配置文件,配置文件包括数据库连接的信息或者Mapper映射文件或者Mapper包路径
2 有了这些就能创建SqlSessionFactory,SqlSessionFactory的生命周期是程序级的,程序运行时候建立,程序结束的时候消亡
3 SqlSessionFactory建立SqlSession,目标是执行sql语句,SqlSession的生命周期是方法级,一个方法中建立,方法结束消亡
4 当用户使用Mapper.xml配置的方法时,mybatis首先会解析动态标签为sql语句的模式,将其封装到MapperStatement中,然后使用executor将sql注入到数据库中执行,返回结果。
5 将返回的对象,通过映射,封装成java对象

mybatis接口绑定

定义接口,将接口中的方法与sql语句进行绑定

Dao接口的工作原理是JDK动态代理,Mybatis运行时会使用JDK动态代理为Dao接口生成代理proxy对象,代理对象proxy会拦截接口方法,转而执行MappedStatement所代表的sql,然后将sql执行结果返回。

两种方式:

1 注解绑定:

就是在接口的方法上面@Select@Update等注解里面包含Sql语句来绑定,当sql较为简单的时候,使用注解容易点

mysql 会话生命周期 sqlsession生命周期面试_缓存


2 xml文件绑定,要指定xml映射文件里面的namespace必须为接口的全路径名。

mysql 会话生命周期 sqlsession生命周期面试_sql_02

#{}和?{}的区别

#{}是预编译处理,将sql中的#{}替换为?,调用PreparedStatement的set方法来赋值,不会引起sql注入
?{} 是字符串替代,将其拼接到sql语句中

mybatis缓存

mybatis为了缓解数据库的压力,提供了缓存机制
分为一级缓存,二级缓存
一级缓存是默认开启的,不需要配置,是SqlSession级别的缓存,只对此SqlSession有效。
在操作数据库过程中,首先会创建SqlSession会话对象,在对象中,有一个HashMap用来保存缓存数据,其他SQLSession是无法访问的。
1.第一次执行select完毕会将查到的数据写入SqlSession内的HashMap中缓存起来
2.第二次执行select会从缓存中查数据,如果select相同切传参数一样,那么就能从缓存中返回数据,不用去数据库了,从而提高了效率。
注意:
如果sql执行了DML操作(update,insert,delete)并commit后,会清空此sqlSession的缓存,避免脏读
一个SqlSession结束后,他的一级缓存也就不存在了。
mybatis的缓存是基于[namespace:sql语句:参数]来进行缓存的,意思就是,SqlSession的HashMap存储缓存数据时,是使用[namespace:sql:参数]作为key,查询返回的语句作为value保存的。

二级缓存

二级缓存是mapper级别的,同一namespace下的所有SqlSession都可以访问

二级缓存默认是不开启的,需要在conf.xml中开启

mysql 会话生命周期 sqlsession生命周期面试_分页_03


在mapper.xml下配置,此mapper下所有的方法都可以使用,这里配置了一个LRU缓存,并每隔60秒刷新,最大存储512个对象,而却返回的对象是只读的

mysql 会话生命周期 sqlsession生命周期面试_sql_04


若想禁用当前select语句的二级缓存,添加useCache="false"修改如下:

mysql 会话生命周期 sqlsession生命周期面试_mysql 会话生命周期_05


1 当一个SqlSession执行了一次Sql操作后,在关闭此SqlSession时,会将其结果存入二级缓存中

2 当另一个SqlSession要执行select时,他会先去自己的一级缓存中找,如果没有,去二级缓存找,还没有去查数据库

注意:

如果sqlsession执行了DML操作并commit了,此mapper下所有的缓存数据都会清空,避免脏读。

mybatis的缓存是基于[namespace:sql语句:参数]来进行缓存的,意思就是,SqlSession的HashMap存储缓存数据时,是使用[namespace:sql:参数]作为key,查询返回的语句作为value保存的。

mybatis 动态sql

解决了复杂sql语句需要拼接的问题

常用的动态sql标签有where,set,

mysql 会话生命周期 sqlsession生命周期面试_sql_06


如果这些条件没有一个能匹配上会发生什么?最终这条 SQL 会变成这样:select * from blog where

这会导致查询失败。如果仅仅第二个条件匹配又会怎样?这条 SQL 最终会是这样:

select * from blog where and title=?

也不对

需要where标签,他会在至少有一个条件判断成功后才插入where,而且不会让and 或or开头

mysql 会话生命周期 sqlsession生命周期面试_分页_07

mybatis 模糊查询

1 先拼接后传入Mapper

就是将要查询的关键字keyword,在代码中拼接好要查询的格式,如%keyword%

String key = “%”+keyWord+"%";

Mapper中:

mysql 会话生命周期 sqlsession生命周期面试_mysql 会话生命周期_08


2 CONCAT()函数

MySQL的 CONCAT()函数用于将多个字符串连接成一个字符串,是最重要的mysql函数之一。

mysql 会话生命周期 sqlsession生命周期面试_缓存_09


3 bind标签

mysql 会话生命周期 sqlsession生命周期面试_sql_10


mybatis 分页插件的使用和原理

1 导入jar包
2 在 MyBatis 配置 xml 中配置拦截器插件
3 在要分页的方法前写
//获取第1页,10条内容,默认查询总数count
PageHelper.startPage(1, 10);
//紧跟着的第一个select方法会被分页
List all = userMapper.findAll();
原理:
pageHelper原理是通过ThreadLocal来存放分页信息,从而可以做到在Service层实现无侵入性的Mybatis分页实现。
PageHelper拦截的是org.apache.ibatis.executor.Executor的query方法。其传参的核心原理是通过ThreadLocal进行的。当我们需要对某个查询进行分页查询时,我们可以在调用Mapper进行查询前调用一次PageHelper.startPage(页数,每页记录数),这样PageHelper会把分页信息存入一个ThreadLocal变量中。在拦截到Executor的query方法执行时会从对应的ThreadLocal中获取分页信息,获取到了,则进行分页处理,处理完了后又会把ThreadLocal中的分页信息清理掉,以便不影响下一次的查询操作。这样就做到了在引入了分页后可以对原来的查询代码没有任何的侵入性。
在进行分页查询时,我们的返回结果一般是一个java.util.List,PageHelper分页查询后的结果会变成com.github.pagehelper.Page类型,其继承了java.util.ArrayList,所以不会对我们的方法声明造成影响