1、#{}和${}的区别是什么?
a、#{}是预编译处理,${}是字符串替换。
b、Mybatis 在处理#{}时,会将 sql 中的#{}替换为?号,调用 PreparedStatement 的 set 方法来赋值;
c、Mybatis 在处理${}时,就是把${}替换成变量的值。
d、使用#{}可以有效的防止 SQL 注入,提高系统安全性
2、xml映射文件中,除了insert|select|update|delete标签之外,还有哪些标签
<resultMap>、<parameterMap>、<sql>、<include>、<selectKey>,加上动态sql的9个标签,trim|where|set|foreach|if|choose|when|otherwise|bind等,其中<sql>为sql片段标签,通过<include>标签引入sql片段,<selectKey>为不支持自增的主键生成策略标签。
3、通常一个映射文件,都会写一个dao接口与之对应,请问这个dao接口的工作原理是什么?dao接口里的方法,参数不同时,方法能重载吗?
dao接口的全路径名就是映射文件namespace,方法名就是映射文件的MappedStatement的id,方法的参数,就是传递给sql的参数。在Mybatis中,每一个<select>、<insert>、<update>、<delete>标签,都会被解析为一个MappedStatement对象。
参考博客: 面试题:mybatis 中的 DAO 接口和 XML 文件里的 SQL 是如何建立关系的?_程序员囧辉-CSDN博客
Dao接口的工作原理是JDK动态代理,Mybatis运行时会使用JDK动态代理为Dao接口生成代理proxy对象,代理对象proxy会拦截接口方法,转而执行MappedStatement所代表的sql,然后将sql执行结果返回。
4、mybatis是如何进行分页的?分页插件的原理是什么?
mybatis插件是通过jdk动态代理来实现的。
加入一个对象被代理多次,配置在前面的拦截器最后被执行。
pagehelper-spring-boot-autoconfigure
5、简述mybatis插件的运行原理,以及如何编写一个插件?
mybatis四大核心对象:
(1)ParameterHandler:处理SQL的参数对象
(2)ResultSetHandler:处理SQL的返回结果集
(3)StatementHandler:数据库的处理对象,用于执行SQL语句
(4)Executor:MyBatis的执行器,用于执行增删改查操作
Executor是真正用来执行sql的语句的对象,调用sqlsession的方法,最终实际上是通过Executor来完成。
配置文件setting标签defaultExecutorType属性。默认simple。
ReuseExecutor相比较于SimpleExecutor做了一点优化,那就是将Statement对象进行了缓存处理,不会每次都创建Statement对象,这样做的话减少了SQL预编译和创建对象的开销。
BatchExecutor从名字上也可以看出来,这是一个支持批量操作的执行器。
三种常用批量插入方法:
1、直接代码循环
2、xml中批量标签foreach
3、 BatchExecutor插入
https://blog.csdn.net/zwx900102/category_8934270.html
mybats拦截器插件就是针对的这4个对象!
自定义mybatis插件,必须实现interceptor接口
6、mybatis执行批量插入时,能返回数据库主键列表吗?
7、mybatis动态sql是做什么的?都有哪些动态sql简述一下动态sql的执行原理
8、mybatis如何将sql执行结果封装为目标对象并返回,都有哪些映射形式?
9、mybatis能执行一对一、一对多的关联查询吗?都有哪些实现方式,以及它们之间的区别
10、mybatis是否支持延迟加载,如果支持,它的实现原理是什么?
11、mybatis的xml映射文件中,不同的xml映射文件,id是否可以重复?
不同的Xml映射文件,如果配置了namespace,那么id可以重复;如果没有配置namespace,那么id不能重复;
原因就是namespace+id是作为Map<String, MapperStatement>的key使用的,如果没有namespace,就剩下id,那么,id重复会导致数据互相覆盖。有了namespace,自然id就可以重复,namespace不同,namespace+id自然也就不同。
但是,在以前的Mybatis版本的namespace是可选的,不过新版本的namespace已经是必须的了。
12、mybatis中如何执行批处理?
设置sqlsession为批量操作类型
sqlsession sqlsession = sqlsessionfactory.opensession(executortype.batch);
try {
namemapper mapper = sqlsession.getmapper(namemapper.class);
for (string name : names) {
mapper.insertname(name);
}
sqlsession.commit();
}catch(Exception e){
e.printStackTrace();
sqlSession.rollback();
throw e;
}
finally {
sqlsession.close();
}
全局配置文件
<configuration>
<!-- ... -->
<settings>
<setting name="defaultExecutorType" value="BATCH"/>
</settings>
<!-- ... -->
</configuration>
13、mybatis中都有哪些Executor执行器,它们之间的区别是什么?
1、SimpleExecutor:每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象。
2、ReuseExecutor:执行update或select,以sql作为key查找Statement对象,存在就使用,不存在就创建,用完后,不关闭Statement对象,而是放置于Map内,供下一次使用。简言之,就是重复使用Statement对象。
3、BatchExecutor:执行update(没有select,JDBC批处理不支持select),将所有sql都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕后,等待逐一执行executeBatch()批处理。与JDBC批处理相同。
作用范围:Executor的这些特点,都严格限制在SqlSession生命周期范围内。
每次调用会使用一个新的sqlsession
14、mybatis中如何指定使用哪一种Executor执行器?
15、Mybatis是否可以映射枚举类?
16、mybatis映射文件中,如果A标签通过include引用了B标签的内容,请问,B标签能否定义在A标签的后面,还是必须在前面?
17、简述mybatis的xml映射文件和mybatis内部数据结构之间的映射关系?
18、为什么说mybatis是半自动化的ORM映射工具?它与全自动的区别在哪里?
1、缓存
1、一级缓存:
也叫本地缓存,在会话(sqlsession)层面进行的缓存。默认开启。
DefaultSqlSession只有两个属性:Configuration(全局的)和Executor(存放缓存)。
在同一会话里面,多次执行相同的sql,会直接从内存取到缓存的结果,不再发送sql到数据库。
生命周期:
开启一个数据库会话时,会创建一个sqlsession对象,SqlSession对象中会有一个新的Executor对象,Executor对象中持有一个新的PerpetualCache对象。当会话结束时,SqlSession对象及其内部的Executor对象还有PerpetualCache对象也一并释放掉。
如果SqlSession调用了close()方法,会释放掉一级缓存PerpetualCache对象,一级缓存将不可用。
如果SqlSession调用了clearCache(),会清空PerpetualCache对象中的数据,但是该对象仍可使用。
SqlSession中执行了任何一个update操作(update()、delete()、insert()) ,都会清空PerpetualCache对象的数据,但是该对象可以继续使用。
工作流程:
不足:
多个会话和分布式环境下,可能有不一样的缓存,存在脏数据。
关闭:
一级缓存无法关闭,但是有俩个级别可以选择。可以设置成statement级别,这样每次查询结束都会清掉一级缓存。
2、二级缓存
范围是namespace级别,可以被多个sqlsession共享。
Mybatis查询数据的顺序是:二级缓存 -> 一级缓存 -> 数据库。
作为一个范围更广的缓存,在sqlsession的外面,否则不能被多个sqlsession共享。而一级缓存在sqlsession内部。
并且,工作在一级缓存之前,只有取不到二级缓存的情况下才到一个会话中取一级缓存。
那么,二级缓存放在哪个对象维护呢?要跨会话共享的话,sqlsession和BaseExecutor一级满足不了要求。实际上,Mybatis用一个装饰器的类,就是CacheExecutor。对于查询请求,会判断二级缓存是否有缓存结果,如果没有,才会委派给真正的查询器Executor实现类,比如SimpleExecutor。 --装饰器模式
开启二级缓存的方法
1、<setting cacheEnable value="true" />
默认开启的,只要没有显示设置false,都会用CacheExecutor装饰基本的执行器
2、在mapper.xml中配置 <cache />标签
启动的时候会创建这个mapper的cache对象,存放在MappedStatement这个对象里(id是mapper接口的全路径.方法名)
增删改标签,默认有flushCache标签=true,会在增删改操作时清空缓存(只清空当前namespace的缓存)。
查询标签,默认有useCache标签=true。
事务提交后,才会添加到二级缓存!!
3、可以使用useCache=“false”属性在单个statementID上关闭二级缓存
注意
1、适合查询为主的应用中使用
2、多个namespace中有针对同一张表的使用,在一个namespace中刷新了缓存,另一个namespace没有刷新,就会出现读到脏数据。所以,推荐在一个mapper操作单表。
3、<cache-ref>可以解决跨namespace的缓存共享问题。代表引用别的namespace的Cache配置,两个namespace的操作使用的是同一个Cache。
参考博客: Mybatis#{}和${}的区别是什么?,Xml映射文件中,除了常见的select|insert|updae|delete标签之外,还有哪些标签?_yuanaili的博客-CSDN博客