# Mybatis(四)表间关系分析,高级映射(一对一,一对多,多对多) 菜鸟日记--day05(下_02)

Mybatis(四)表间关系分析,高级映射(一对一,一对多,多对多) 菜鸟日记–day05(下_02)

花了很多时间,去看sql复杂查询,更新慢了
电脑断电写的太急,绿色补更

一、表间关系分析

1.分析数据库表的方法

思路:
需要分模块的对多张表进行逻辑分析
    表记录的数据内容
    表中重要字段(非空、外键, 一般自增id没有实际意义)
    分析表和表之间的关系(确立业务意义的基础上)
业务意义:
    只有在一定业务逻辑下表和表之间的关系才能明确。
    比如:
        用户表和订单表到底是不是一对多关系(有特殊情况可能是1对1)

2.表间关系分析

1)虚拟几张表,并确定业务

有四张表分别为(表名意思太明显就不讲解了):
用户表:一个用户能创建多个订单
订单表:一个订单只能由一个用户创建,一个订单下可能包含多个子订单(单个商品)。
订单详情表:存储子订单信息,一个子订单信息能确定属于哪个订单,并且存储了一个相关商品的id
商品信息表:一个商品信息 存在于多个订单详情(子订单)上。
依次通过id进行主外键关联,就正常那种都能想到的关联

2)表间关系整理

首先明确 “到” 与 “和” 
到- 理解成从1条记录可以对应到另一张表中几条记录。
直接关系分析
1.用户表 和 订单表
    用户表 到 订单表 1对多
    订单表 到 用户表 1对1
2.订单表 和 订单详情表
    订单表 到 订单详情表 1对多
    订单详情表 到 订单表 1对1
下面暂时用不到,也很好分析 过。。
3.订单详情表 和 商品表
4.订单表 和 商品表
5.用户表 和 商品表
等等 

3.需求分析

1)需求

暂时有两种需求:
1步1步来 
第一种
    查询订单信息,同时得到用户名等相关信息。
第二种
    在第一种的基础上,查询得到所有订单详情(子订单)。

2)分析(这标题分的。。)

第一种需求
 返回结果,包含订单信息本身全部字段,加上用户id、用户名、用户性别等(跟需求来)。
返回结果实现(知识点):

resultType:定义订单的扩展类型pojo(包含用户id、用户名、用户性别等需求信息-- 具体是订单还是用户的扩展类型,看你到底想得到什么,如果搜索结果中用户信息占用比较多久继承用户写个用户的扩展类,再加上订单相关信息属性)
 这个没啥说的
resultMap:按上述例子,扩展类中增加用户相关属性,实际关联查询到信息并没有跟用户java对象进行映射。
 那么现在不添加用户信息字段属性。在扩展类中加入 一个User成员对象。通过resultMap对结果集映射,在resultMap中定义关联查询结果和用户(Order扩展类的User类属性)的映射
  特点:很明显指定resultMap确定返回结果,可以实现对关联查询的信息进行映射

为什么resultType不适合用来进行关联映射?
 仅本人观点,select 查询的结果 对每一条记录都可以看做一个键值对集合,每个查询结果键值对都是平级的,resultType将这些结果返回,resultType指定的类型对象接收这些键值对数组,来跟自己的成员属性来一一对应,关联查询到的信息是无法被特殊待遇的,通过多列合并成1列将关联查询到的信息(比如用户信息)进行糅合,强制分级,将其划分进第二级来进行区分也很复杂。
 通过定义resultMap 对这些查询结果(键值对集合),进行自定义划分处理,可以很容易的将各个对应信息丢进相应pojo类型对象中去。仅个人理解哈。

使用resultMap 和 使用resultType 选择
 如果没有特殊说明的情况下 使用resultType,如果要求需要进行映射,那么使用resultMap来确定返回类型。

第二种需求
 在第一种需求的基础上,查询订单信息要包含所有订单的子信息(子订单号,子订单价格,子订单对应商品id等),很明显,订单记录和订单详情记录存在一对多关系。那么则有如下两种方案解决问题。
resultType 指定返回值类型:
 首先创建订单扩展类,在需求一的对应-resultType返回类型-的扩展类的基础上加入集合属性来存储详情信息。查询结果直接做映射是很困难的,加入中间类对象(根据每条查询结果写自定义类),sql查询结果中同一条订单号,对应多条子订单(订单详情)记录,查询结果的订单id肯定是多条重复的,想让订单id保持唯一,可以将结果取出来后对结果集(中间类集合)通过两次循环将结果写入订单扩展类(外层循环创建订单信息录入相关,内层循环将详情信息写入订单信息内的详情集合)。
 这种方式显然比较麻烦。
resultMap来指定返回值类型:
 也是相对于需求一(resultMap实现)来说,需求二相当于在结果集中加入一个list集合来存储订单详情类(子订单类好理解一点)对象,在resultMap中定义映射,正好resultMap的定义中可以实现,对list集合存储pojo对象,这一情况实现关系映射,正好满足所需。具体resultMap定义后面说


3)sql 这里就做简写,写出思路

之前连接都是用 on 连接,看视频中使用的where 做连接。太晚了,等有时间再分析。
实现上面的需求一:
    select 订单表.* ,用户表.所需字段信息(自己随便写) from 订单表,用户表 where 订单表.userId=用户表.id
    这里2张表都有id字段 用户表的id字段和订单表的用户id字段值相同(肯定滴啊,外键啊)不要select 用户表.id 
    第二种需求中id字段会重复,必须要在select 字段后加别名了
需求二:
     select 订单表.* ,用户表.所需字段信息(自己随便写) 
     from 订单表,用户表,订单详情表
     where 
     订单表.userId=用户表.id 
     And 订单详情表.订单i=订单表.id

二、具体Mybatis实现

1)resultType

没啥好记得,创建自定义类将查询结果进行一一封装

2)resultMap

mapper接口创建,mapper.xml文件关联,测试方法都过。。
 主要知识点在于resultMap的定义:

<resultMap type="这里指定最终映射的pojo类" id="唯一标识">
	<!--这几行定义的是pojo(订单信息类)内的第一级属性(简单类型属性)-->
	<id column="sql查询结果的列名,这一行是订单主键" properties="列名对应pojo类中属性名,这一行是订单id属性"/>
	<result column="普通列名" properties="列对应pojo成员属性"/>
	...
	<!--这里开始配置订单类内部的客户属性映射
		association:用于映射关联查询单个对象(这里映射User)的信息
			  属 性: property:用于指定将查询到的信息关联到哪个成员对象中去(也就是输入订单类中的用户类成员名)
			  		  javaType:上面指定了给哪个对象做映射,在这里定义映射对象的类型(也就是用户类的全限定名)
			  		  有点长,这里备注下面直接写值,
   -->
	<association property="user" javaType="包名.User">
		<id column="user_id" property="注对应用户类中的那个属性比如 user_id对应:id"/>
		<result ... />	
		...
	<association/>

	<!--这里配置订单类内部的集合属性映射(集合成员是详情类)
		collection:对关联查询信息查询到的--多条--记录进行映射(记录订单详情信息)
			   属性:property:和association意义一样(这里指定 订单详情信息集合变量名)
			   		 ofType:  指定集合成员pojo的类型(订单详情类全限定名)
	-->
	<collection property="集合名称" ofType="包名.订单详情类名">
		<id ..订单详情唯一标识列../>
		<result .. />
		...
	</collection>
</resultMap>

上述是满足需求二的resultMap,和需求一相比仅仅是多了一个list集合,其他的一模一样 可以通过resultMap的extends属性来继承需求一的resultMap
电脑电量限制,写的有点急。

补充:多对多查询
 还是上面四张表

表间关系 用户和商品表之间通过订单表和订单详情表关联

 查询用户和商品的对应关系多对多,用户到商品一个用户买过多个商品(查询结果为)

用户有多条订单信息
订单信息有多条订单详情
订单详情对应一条商品

 根据这个关系:修改pojo类型(默认原来内容仅和数据库列一一对应)

订单详情:增加一个商品类型属性 。
订单列表:增加订单详情类型集合属性。
用户列表:增加一个订单类型集合属性。

 通过这样实现一种由用户到商品的关联。

pojo类按上述进行更改
mapper.xml 编写sql语句,需求二是3张表关联 这里不过再加上商品表 用订单详情id做关联。
resultMap的更改,由于涉及到两个 1对多关系 列表中包含列表 需要在collection 中嵌套 collection 商品信息用association,没啥说的就这样儿吧很明白了

如果不需要上述的层层包含关系查询:购买商品的用户信息和商品信息 (多对多) 不进行去重
直接使用resultType 然后定义各个属性的扩展类来接收,就很简单。


pojo和po简单理解成
po就是持久层对象,他的每一条属性和数据库表相互对应,
pojo :简单的Java对象,实际就是普通JavaBeans,是为了避免和EJB混淆所创造的简称。
另外:
是中间对象,不包含什么逻辑,单纯用来存储对象,较为灵活可以根据需求灵活改动。
持久化以后就是PO
直用它传递就是DTO
用来对应表示层就是VO

猜你喜欢

转载自blog.csdn.net/qq_38325853/article/details/85150020