125.mybatis 中 #{}和 ${}的区别是什么?
#{}是预编译处理,${}是字符串替换
Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值
Mybatis在处理${}时,就是把${}替换成变量的值
使用#{}可以有效地防止SQL注入,提高系统安全性
126.mybatis 有几种分页方式?
1.数组分页
2.sql分页
3.拦截器分页
4.RowBounds分页
127.RowBounds 是一次性查询全部结果吗?为什么?
RowBounds(逻辑分页)会一次性查询全部结果,该操作是对ResultSet结果集进行分页
128.mybatis 逻辑分页和物理分页的区别是什么?
逻辑分页是通过对ResultSet结果集进行分页,物理分页是直接在数据库中进行分页
逻辑分页内存开销比较大,在数据量比较小的情况下效率比物理分页高;在数据量大的情况下,内存开销过大,容易内存溢出,不建议使用;
物理分页内存开销比较小,在数据量比较小的情况下效率比逻辑分页还是低,在数据量很大的情况下,建议使用物理分页
129.mybatis 是否支持延迟加载?延迟加载的原理是什么?
Mybatis仅支持association关联对象和collection关联集合对象的延迟加载,association指的就是一对一,collection指的是一对多查询。在mybatis配置文件中,可以配置是否启用延迟加载lazyLoadingEnabled=true|false
原理:使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用a.getB().getName(),拦截器invoke()方法发现a.getB()是null值,那么就会单独发送事先保存好的查询关联B对象的sql,把B查询上来,然后调用a.setB(b),于是a的对象b属性就有值了,接着完成a.getB().getName()方法的调用。这就是延迟加载的基本原理.
130.说一下 mybatis 的一级缓存和二级缓存?
一级缓存:基于PerpetualCache的HashMap本地缓存,其存储作用域为Session,当session flush或close会后,该session中的所有cache就将清空,默认打开一级缓存。
二级缓存与一级缓存机制相同,默认也采用PerpetualCache,HashMap存储,不同自于存储作用域为Mapper(Namespace),并且可以自定义存储源,默认不打开二级缓存,要开启二级缓存,使用二级缓存属性类需要实现Serializable序列化接口,可在他的映射文件中配置<cache/>;
对于缓存数据更新机制,当某个作用域进行了C/U/D操作之后,默该作用于下所有select中的缓存将被clear
131.mybatis 和 hibernate 的区别有哪些?
Mybatis和hibernate不同,它不完全是一个ORM框架,因为MyBatis需要自己编写语句
Mybatis直接编写原生态sql,可以严格控制sql执行性能,灵活度高,非常适合对关系型数据模型要求不高的软件开发,如果需要实现支持多种护具库的软件,需要自定义多套sql映射文件,工作量大
Hibernate对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件,如果用hibernate开发可以节省很多代码,提高效率
132.mybatis 有哪些执行器(Executor)?
SimpleExecutor: 每执行一次update或select,就开启一个statement对象,用完立刻关闭Statement对象。
ReuseExeccutor: 执行update或select,以sql作为key查找Statment对象,存在就使用,不存在就创建,用完后,不关闭Statment对象,而是放置于Map内,共下一次使用。简言之,就是重复使用Statement对象
BatchExecutor: 执行update(没有select,JDBC批处理不支持select),将所有sql都添加到批处理中(addBatch),等待统一执行(executeBatch()),它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕之后,等待逐一执行executeBatch()批处理,与JDBC批处理相同。
133.mybatis 分页插件的实现原理是什么?
分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。
134.mybatis 如何编写一个自定义插件?