- #{}和${}的区别是什么?
- #{}是预编译处理#{}可以防止Sql 注入,它会将所有传入的参数作为一个字符串来处理。
- ${}是字符串替换。${} 则将传入的参数拼接到Sql上去执行,一般用于表名和字段名参数,$ 所对应的参数应该由服务器端提供,前端可以用参数进行选择,避免 Sql 注入的风险
Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;
Mybatis在处理时,就是把{}替换成变量的值。
使用#{}可以有效的防止SQL注入,提高系统安全性。
- Mybatis是如何进行分页的?分页插件的原理是什么?
Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页,可以在sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。
分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。
Mybatis是如何将sql执行结果封装为目标对象并返回的?都有哪些映射形式?
第一种是使用<resultMap>标签,逐一定义列名和对象属性名之间的映射关系。
第二种是使用sql列的别名功能,将列别名书写为对象属性名,比如T_NAME AS NAME,对象属性名一般是name,小写,但是列名不区分大小写,Mybatis会忽略列名大小写,智能找到与之对应对象属性名,你甚至可以写成T_NAME AS NaMe,Mybatis一样可以正常工作。
有了列名与属性名的映射关系后,Mybatis通过反射创建对象,同时使用反射给对象的属性逐一赋值并返回,那些找不到映射关系的属性,是无法完成赋值的。Xml映射文件中,除了常见的select|insert|update|delete标签之外,还有哪些标签?
还有很多其他的标签,加上动态sql的9个标签,trim|where|set|foreach|if|choose|when|otherwise|bind等,其中为sql片段标签,通过标签引入sql片段,为不支持自增的主键生成策略标签。简述Mybatis的插件运行原理,以及如何编写一个插件
Mybatis仅可以编写针对ParameterHandler、ResultSetHandler、StatementHandler、Executor这4种接口的插件.
Mybatis使用JDK的动态代理,为需要拦截的接口生成代理对象以实现接口方法拦截功能,每当执行这4种接口对象的方法时,就会进入拦截方法,具体就是InvocationHandler的invoke()方法,当然,只会拦截那些你指定需要拦截的方法。实现Mybatis的Interceptor接口并复写intercept()方法,然后在给插件编写注解,指定要拦截哪一个接口的哪些方法即可,记住,还需要在配置文件中配置你编写的插件。
- 一级、二级缓存
1)一级缓存: 基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该 Session 中的所有 Cache 就将清空。
2)二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap 存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。要开启二级缓存,你需要在你的 SQL 映射文件中添加一行:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29<cache/>
````
<br/>
3)对于缓存数据更新机制,当某一个作用域(一级缓存 Session/二级缓存Namespaces)的进行了C/U/D 操作后,默认该作用域下所有 select 中的缓存将被 clear。<br/>
7. Mybatis是否支持延迟加载?如果支持,它的实现原理是什么?<br/>
Mybatis仅支持association关联对象和collection关联集合对象的延迟加载,association指的就是一对一,collection指的就是一对多查询。<br/>
在Mybatis配置文件中,可以配置是否启用延迟加载lazyLoadingEnabled=true|false。<br/>
它的原理是,使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用a.getB().getName(),拦截器invoke()方法发现a.getB()是null值,那么就会单独发送事先保存好的查询关联B对象的sql,把B查询上来,然后调用a.setB(b),于是a的对象b属性就有值了,接着完成a.getB().getName()方法的调用。这就是延迟加载的基本原理。
8.
对于支持自动生成主键的数据库,如Mysql、sqlServer,可以通过 Mybatis元素**useGeneratedKeys**返回当前插入数据主键值到输入类中。
对于不支持自动生成主键的数据库。Oracle、DB2等,可以用**元素selectKey **回当前插入数据主键值到输入类中。(同时生成一个自定义的随机主键)。
9.
1、第一种:
DAO 层的函数
public UserselectUser(String name,String area);
对应的 xml,
参数,更多参数一致往后加即可。
```<select id="selectUser"resultMap="BaseResultMap">
select * fromuser_user_t whereuser_name =
anduser_area=
</select>
2、第二种: 使用 @param 注解:
1 | public interface usermapper { |
然后,就可以在 xml 像下面这样使用(推荐封装为一个 map,作为单个参数传递给 mapper):
1 | select id, username, hashedpassword |
3、第三种:多个参数封装成 map
1 | try { |
嵌套查询和嵌套结果
嵌套查询 | 嵌套结果 |
---|---|
嵌套查询是在查询 SQL 后再进行一个(子)查询 | 嵌套结果是一个多表查询的 SQL 语句 |
会执行多条 SQL 语句 | 只有一条复杂的 SQL 语句(多表连接) |
SQL语句编写较为简单 | SQL语句编写较为复杂 |