resultMap(数据库字段映射)、sql、include、selectKey 和动态 sql 标签: if、where、set、foreach、trim、choose、when(这三个是多条件判断,相当于 if/else if)、otherwise等
项目中,通常一个 xml 映射文件,就会写一个 Dao 接口来对应。Dao 接口也就是 Mapper 接口,接口的全限名映射的就是文件中的 namespace 值,接口的方法名映射的就是文件中 MappedStatement 的 id 值,接口方法的参数就是传递 sql 的参数。Mapper 接口没有实现类,当调用接口方法的时候,接口全限名 + 方法名拼接字符串作为 key,可以定位一个 MappedStatment。每一个增删改查的标签都会被解析为一个 MappedStatment 对象【比如 com.mhn.mapper. StudentDao.findStudentById,就是找 namespace 为 com.mhn.mapper. StudentDao 下面 id = findStudentById 的 MappedStatement】Dao 接口里的方法可以重载,但映射的 xml 中 ID 是不可重复的
第一种使用 resultMap 标签,逐个定义列名与对象属性名之间的映射关系。第二种使用 sql 别名的功能,设置别名与对象属性名对应。存在列名和属性名的映射关系后,MyBatis 通过反射创建对象,同时使用反射给对象的属性逐个赋值并返回
MyBatis 只支持 assocation(一对一)关联对象和 collection(一对多)关联集合对象的延迟加载,可以通过配置文件 lazyLoadingEnableed = true/false 来开启关闭延迟加载
原理是,使用 CGLIB 创建目标的代理对象,当调用目标方法的时候,进入拦截器方法,比如调用了 a.getB().getName(),拦截器发现 a.getB() 是 null 值,那么就会单独发送保存好的查询关联 B 对象的 sql,吧 B 查询出来,然后调用 a.setB(b),这样 a 对象的 b 属性就存在值了,然后再完成 a.getB().getName() 方法的调用
为了提高数据库查询性能,尽量使用单表查询,因为单表查询要比多表查询更快,一开始先查询单表,当需要关联信息,再进行关联查询就叫做延迟加载
不同的 xml 映射文件,如果配置了 namespace 那么 id 可以重复,如果没有配置 namespace 那么 id 不能重复。
虽然解析 xml 映射文件是按照顺序解析的,但被引用的 B 标签依然可以定义在任何地方,MyBatis 都可以正确识别。因为 MyBatis 解析 A 标签,发现 A 标签引用了 B 标签,但是 B 标签还没被解析到,那么会吧 A 标签标记为未解析状态,继续解析剩下的标签包含 B 标签,当所有标签解析完以后,会重新解析被标记未解析状态的标签,这时候再解析 A 标签的时候,B 标签就已经存在,A 标签也就可以正常解析了
Hibernate 属于全自动,使用 Hibernate 查询关联对象或者关联集合对象的时候,可以根据对象关系模型直接获取,所以是全自动的。而 MyBatis 在查询关联对象或关联集合对象的时候,需要手动编写 sql 来完成,所以是半自动 ORM 映射工具