1 解决列名和属性名不一致问题
如果查询时使用 resultType 属性, 表示采用 MyBatis 的Auto-Mapping(自动映射)机制, 即相同的列名和属性名会自动匹配. 因此, 当数据库表的列名和类的属性名不一致时, 会导致查不到数据.
如下图:
运行结果:
解决该问题可以有两种方式:
(1)列别名
查询时, 可以通过列别名的方式将列名和属性名保持一致, 继续使用自动映射,从而解决该问题. 但是较为麻烦. 不推荐使用
(2)使用<resultMap>标签
<resultMap>用于自定义映射关系, 可以由程序员自主制定列名和属性名的映射关系. 一旦使用 resultMap, 表示不再采用自动映射机制.
2 多表关联查询
首先建立两张表----学生表和班级表
如下:
(1) 业务装配实现多表查询(多对一)
其实业务装配是将两个单表查询组合到一起,在业务装配时引进service层
注意: 在实现业务装配时,出现多个异常问题
首先, 在mapper中创建两个接口之后,核心配置文件的扫描设置仍然是扫描单个文件导致出现异常
然后, 就是在ClazzMapper.xml和StudentMapper.xml文件中两个sql语句写反,导致绑定时出现问题
最后, 就是一个最严重的问题,就是表中的名称t_students 在StudentMapper.xml文件的sql语句中写成了t_student 导致在运行结果无法显示
所以!谨记!!!能粘贴的一定不要手写!!!!
(1.1)实体类
创建班级类(Clazz)和学生类(Student), 并在 Student 中添加一个 Clazz 类型的属性, 用于表示学生的班级信息.
(1.2)mapper层
提供StudentMapper和ClazzMapper, StudentMapper查询所有学生信息, ClazzMapper 根据编号查询班级信息.
(1.3)service层 ---业务装配
调用 mapper 层, 先查询所有学生, 再根据每个学生的班级编号查询班级信息, 手动进行组装, 称之为业务装配.
这一点要理解:
//通过获取学生中cid班级号来查询班级信息,再将班级信息放到学生信息里
student.setClazz(clsMapper.selectById(student.getCid()));
(1.4) 测试代码
业务装配的优缺点:
sql语句很简单,但是代码使用太多,需要手动装配
(2)通过mybatis完成的多表查询,称之为N+1查询 -- 依赖于resultMap标签
核心思想仍然属于业务装配
注意: 1)在这里也出现异常,因为忘了修改StudentMapper.xml 的resultMap="smap"
如下:
2)重复的映射关系,同名时可以省略,但只能在N+1关系中省略,在其他关系中即使同名也不能省略
(2.1)在mapper层中
提供StudentMapper和ClazzMapper, StudentMapper查询所有学生信息, ClazzMapper 根据编号查询班级信息.在StudentMapper 中使用<association>设置装配.
a) <association>用于关联一个对象
property: 指定要关联的属性名
select: 设定要继续引用的查询, namespace+id
column: 查询时需要传递的列
(2.2)service 层
由于装配已经完成, service 层只需要调用 mapper 即可, 不需要再进行装配了.
如图:
以上两种方法的缺点是:执行的代码太多
因此可以使用resultMap的关联方式实现多表查询(多对一)
(3) resultMap 的关联方式实现多表查询(多 对一)
(3.1)mapper层
a) 在 StudentMapper.xml 中定义多表连接查询 SQL 语句, 一次性查到需要的所有数据, 包括对应班级的信息.
b) 通过<resultMap>定义映射关系, 并通过<association>指定对象属性的映射关系. 可以把<association>看成一个<resultMap>使用. javaType 属性表示当前对象, 可以写全限定路径或别名.
注意:<association property="clazz" javaType="clazz">
这里的两个clazz其实意义并不相同:前面clazz指的是名字,而后面指的时类型
外面一层resultMap用来设定student的属性,而里面的<association>再为student的clazz属性赋值
总结:N+1方式查询每条sql语句都很简单,但是代码复杂,每次都要装配
而关联方式的多表查询,sql语句复杂一些,值查询一次所有数据就会出现,也不需要再在mapper中添加class文件
(4)resultMap的N+1方式实现多表查询(一对多)
(4.1)实体类
在班级类中定义一个学生集合,用于存放该班级的所有学生的信息
(4.2)mapper层
提供ClazzMapper和StudentMapper, ClazzMapper查询所有班级信息, StudentMapper 根据班级编号查询学生信息. 在 ClazzMapper 中使用<collection>设置装配.
a) <collection>用于关联一个集合
property: 指定要关联的属性名
select: 设定要继续引用的查询, namespace+id
column: 查询时需要传递的列
如图:
(4.3)server层
(5)resultMap的关联方式实现多表查询(一对多)
(5.1)mapper层
a) 在 ClazzMapper.xml 中定义多表连接查询 SQL 语句, 一次性查到需要的所有数据, 包括对应学生的信息.
b) 通过<resultMap>定义映射关系, 并通过<collection>指定集合属性泛型的映射关系. 可以把<collection>看成一个<resultMap>使用. ofType 属性表示集合的泛型, 可以写全限定路径或别名.
如图:
(6)通过Auto_Mapping实现多表查询 --自动映射查询
a) 通过 MyBatis 的 Auto-Mapping 机制及数据库查询时的别名结合, 可以方便的实现多表查询.
b) SQL 语句中, 别名出现特殊符号时, 必须进行处理. MySQL可以使用(``)符号, Oracle 可以使用("")符号.
(6.1)mapper
所以Auto_Mapping实现多表查询优点是代码很少,方便查询
缺点是: sql语句书写非常严格,不能出一点问题,而且在起别名时必须使用``符号
如图: