mybatis 多表关联查询_Java修行第041天--MyBatis框架(下)--多表查询

1 解决列名和属性名不一致问题

如果查询时使用 resultType 属性, 表示采用 MyBatis 的Auto-Mapping(自动映射)机制, 即相同的列名和属性名会自动匹配. 因此, 当数据库表的列名和类的属性名不一致时, 会导致查不到数据.

如下图:

72525b53bad7a59a7c186d8052baff8a.png

运行结果:

4f6bb795f694277c6530620ede1bf61e.png

解决该问题可以有两种方式:

(1)列别名

查询时, 可以通过列别名的方式将列名和属性名保持一致, 继续使用自动映射,从而解决该问题. 但是较为麻烦. 不推荐使用

(2)使用<resultMap>标签

<resultMap>用于自定义映射关系, 可以由程序员自主制定列名和属性名的映射关系. 一旦使用 resultMap, 表示不再采用自动映射机制.

412e8b7b9cdcce19e4c070c2170d9966.png

7b7d986462aaee307807700e41e73499.png

2 多表关联查询

首先建立两张表----学生表和班级表

如下:

ceef64f63423affece800c7993737542.png

d876025c06f95d4e25ddcc91dbcdcf5b.png

(1) 业务装配实现多表查询(多对一)

其实业务装配是将两个单表查询组合到一起,在业务装配时引进service层

注意: 在实现业务装配时,出现多个异常问题

首先, 在mapper中创建两个接口之后,核心配置文件的扫描设置仍然是扫描单个文件导致出现异常

f4c5d04b5dec08df69bdbe787e2a2c4a.png

然后, 就是在ClazzMapper.xml和StudentMapper.xml文件中两个sql语句写反,导致绑定时出现问题

最后, 就是一个最严重的问题,就是表中的名称t_students 在StudentMapper.xml文件的sql语句中写成了t_student 导致在运行结果无法显示

所以!谨记!!!能粘贴的一定不要手写!!!!

(1.1)实体类

创建班级类(Clazz)和学生类(Student), 并在 Student 中添加一个 Clazz 类型的属性, 用于表示学生的班级信息.

a4a74b0a9a3f17b52798093181d4bfb7.png

(1.2)mapper层

提供StudentMapper和ClazzMapper, StudentMapper查询所有学生信息, ClazzMapper 根据编号查询班级信息.

1079e959d0b3bb1b5f7173dc3287369a.png

(1.3)service层 ---业务装配

调用 mapper 层, 先查询所有学生, 再根据每个学生的班级编号查询班级信息, 手动进行组装, 称之为业务装配.

679fbc31658472f4ffe675297b96f0c4.png

这一点要理解:

//通过获取学生中cid班级号来查询班级信息,再将班级信息放到学生信息里

student.setClazz(clsMapper.selectById(student.getCid()));

10bf7e841d4379909fa9a3d4a3e9af77.png

(1.4) 测试代码

业务装配的优缺点:

sql语句很简单,但是代码使用太多,需要手动装配

fd76c1b442755b64deca79cdc4eb8fc5.png

(2)通过mybatis完成的多表查询,称之为N+1查询 -- 依赖于resultMap标签

核心思想仍然属于业务装配

注意: 1)在这里也出现异常,因为忘了修改StudentMapper.xml 的resultMap="smap"

如下:

9d7ee1472449f53a59418350811f9e02.png

2)重复的映射关系,同名时可以省略,但只能在N+1关系中省略,在其他关系中即使同名也不能省略

537bbb752f9accf944c38c4df83ef282.png

(2.1)在mapper层中

提供StudentMapper和ClazzMapper, StudentMapper查询所有学生信息, ClazzMapper 根据编号查询班级信息.在StudentMapper 中使用<association>设置装配.

a) <association>用于关联一个对象

property: 指定要关联的属性名

select: 设定要继续引用的查询, namespace+id

column: 查询时需要传递的列

dafc817f03606d7ee49fb931c7c92345.png

(2.2)service 层

由于装配已经完成, service 层只需要调用 mapper 即可, 不需要再进行装配了.

如图:

f46a1f8feae33a9a92ef9cf7ee92f424.png

以上两种方法的缺点是:执行的代码太多

因此可以使用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属性赋值

81c15df8f9a74ed493eeead0dfcbe380.png

总结: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: 查询时需要传递的列

如图:

e9ca1f3829a2bc53b5b95e850ec7fdeb.png

(4.3)server层

faf7b08a1223d7a97aaf616ad4e54fda.png

(5)resultMap的关联方式实现多表查询(一对多)

(5.1)mapper层

a) 在 ClazzMapper.xml 中定义多表连接查询 SQL 语句, 一次性查到需要的所有数据, 包括对应学生的信息.

b) 通过<resultMap>定义映射关系, 并通过<collection>指定集合属性泛型的映射关系. 可以把<collection>看成一个<resultMap>使用. ofType 属性表示集合的泛型, 可以写全限定路径或别名.

如图:

895d0380a4f52c60bd4b0af43aac33d9.png

(6)通过Auto_Mapping实现多表查询 --自动映射查询

a) 通过 MyBatis 的 Auto-Mapping 机制及数据库查询时的别名结合, 可以方便的实现多表查询.

b) SQL 语句中, 别名出现特殊符号时, 必须进行处理. MySQL可以使用(``)符号, Oracle 可以使用("")符号.

(6.1)mapper

所以Auto_Mapping实现多表查询优点是代码很少,方便查询

缺点是: sql语句书写非常严格,不能出一点问题,而且在起别名时必须使用``符号

如图:

d87656751af67091340db75bc8627418.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值