<>一对一(resultType实现方式)

我们这里就利用订单和用户模型,从订单角度出发,一个订单只能给一个用户创建,所以是一对一,但是从用户角度出发,一个用户是可以创建多个订单的,所以是一对多。但是我们这里从订单角度出发,那么就可以当成一对一来处理
1.这样我们就建立一个需求:查询订单并关联查询下单用户

2.创建用户表和订单表并建立好关系
用户表
CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username`
varchar(32) NOT NULL COMMENT '用户名称', `birthday` date DEFAULT NULL COMMENT '生日',
`sex` char(1) DEFAULT NULL COMMENT '性别', `address` varchar(256) DEFAULT NULL
COMMENT '地址', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT
CHARSET=utf8
订单表
CREATE TABLE `orders` ( `id` int(11) NOT NULL AUTO_INCREMENT, `user_id`
int(11) NOT NULL COMMENT '下单用户id', `number` varchar(32) NOT NULL COMMENT '订单号',
`createtime` datetime NOT NULL COMMENT '创建订单时间', `note` varchar(100) DEFAULT
NULL COMMENT '备注', PRIMARY KEY (`id`), KEY `FK_orders_1` (`user_id`),
CONSTRAINT `FK_orders_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON
DELETE NO ACTION ON UPDATE NO ACTION ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT
CHARSET=utf8
然后我们手动插入一点儿数据

3.针对需求编写sql语句
查询订单所有信息并关联查询订单用户信息

4.有了sql语句之后我们就可以根据创建pojo类
订单pojo,生成属性的getter和setter方法

既然订单用户只有三条属性,那么我们选择新建一个类继承这个订单pojo即可

5.既然pojo类也有了,那么将查询结果映射到哪儿呢?显然是映射到这个子类这里,因为子类是可以通过父类的getter方法得到父类的所有属性的(尽管这些属性是private的),所以就可以编写Mapper.xml文件了

6.那么就可以根据mapper.xml文件编写mapper接口了(使用mapper接口代理的方式开发dao)

7.好了这样就可以写个测试类来测试一下

8.我们采用debug的方式来查看一下结果

<>一对一(resultMap实现方式)

使用resultMap可以将关联查询出来的信息映射到某个pojo的属性上,比如这里我们可以在Orders类中引入一个用户pojo当作其属性,然后将关联结果映射到这个属性上即可。
1.新建一个User类

2.在Orders中添加User属性,生成getter和setter方法

3.采用resultMap的方式编写mapper.xml文件,编写这个resultMap时我们可以对应这数据库查询结果来做,会发现没这么乱,写好id的唯一标识,对着查询结果的字段和映射的pojo的属性名

<!--定义resultMap 将整个查询结果映射到Orders中 --> <resultMap id="OrderUserResultMap"
type="orders"> <!--column指定查询列中的唯一标识 property指定映射类型的属性名 --> <id column="id"
property="id"/> <!--普通列同上规则--> <result column="user_id" property="userId"/>
<result column="number" property="number"/> <result column="createtime"
property="createtime"/> <result column="note" property="note"/> <!--配置关联映射信息
property:将关联的信息映射到Orders类的哪个属性上 javaType:被映射的信息是什么类型 --> <association
property="user" javaType="user"> <!--关联查询的唯一标识 column:指定查询的唯一标识用户的列名
(orders表的外键user_id是建立再user表的主键id上的) property:映射到用户的哪个属性上 --> <id
column="user_id" property="id"/> <!--普通属性同上--> <result column="username"
property="username"/> <result column="sex" property="sex"/> <result
column="birthday" property="birthday"/> <result column="address"
property="address"/> </association> </resultMap>
<!--查询订单同时关联查询订单用户信息,使用上面定义好的resultMap--> <select id="findOrdersUserResultMap"
resultMap="OrderUserResultMap"> SELECT orders.*, USER.username, USER.birthday,
USER.sex, USER.address FROM orders, USER WHERE orders.user_id = user.id
</select>
4.编写Mapper接口

5.测试类(在上面测试类的基础上再加一个单元测试)

6.结果

<>一对一查询总结

1.resultType:使用resultType实现较为简单,如果pojo中没有包括查询出来的列名,需要增加列名对应的属性,即可完成映射,所以如果没有查询结果的特殊要求建议使用resultType。

2.resultMap:需要单独定义resultMap,实现有点麻烦,如果对查询结果有特殊的要求,使用resultMap可以完成将关联查询映射pojo的属性中,虽然resultMap麻烦,但是resultMap可以实现延迟加载

<>一对多查询(建议使用resultMap)

因为如果使用resultType可能会查询出重复的数据,如果要避免这种情况发生那么又要自己写循环判断条件来实先,比较麻烦,为什么这么说呢。我们先来分析一个需求先

1.实现一个查询订单的同时查询用户信息和订单的详情信息,订单详情里面肯定有商品信息把,所以要创建多一个商品表,然后我们就可以将查询出来的数据映射到这个订单表上,所以我们只在订单上添加订单详情属性,然后编写resultMap将关联信息映射到这个属性上即可

下面是商品表
CREATE TABLE `items` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name`
varchar(32) NOT NULL COMMENT '商品名称', `price` float(10,1) NOT NULL COMMENT
'商品定价', `detail` text COMMENT '商品描述', `pic` varchar(64) DEFAULT NULL COMMENT
'商品图片', `createtime` datetime NOT NULL COMMENT '生产日期', PRIMARY KEY (`id`) )
ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8
2.创建一个订单详情表,和订单表以及商品表构建好关系
CREATE TABLE `orderdetail` ( `id` int(11) NOT NULL AUTO_INCREMENT, `orders_id`
int(11) NOT NULL COMMENT '订单id', `items_id` int(11) NOT NULL COMMENT '商品id',
`items_num` int(11) DEFAULT NULL COMMENT '商品购买数量', PRIMARY KEY (`id`), KEY
`FK_orderdetail_1` (`orders_id`), KEY `FK_orderdetail_2` (`items_id`),
CONSTRAINT `FK_orderdetail_1` FOREIGN KEY (`orders_id`) REFERENCES `orders`
(`id`) ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT `FK_orderdetail_2`
FOREIGN KEY (`items_id`) REFERENCES `items` (`id`) ON DELETE NO ACTION ON
UPDATE NO ACTION ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8
3.手动插入一下数据到新建的两个表中

4.针对需求查询一下结果

5.针对sql语句就可以编写resultMap以及mapper.xml文件了

根据分析可以知道,前面一对一我们已经进行了订单和用户的关联查询,且也编写了resultMap,那么就可以使用extends继承已经编写好的resultMap,然后再写新的就行了,和java的继承类似
<!--定义订单关联查询用户及订单明细ResultMap--> <resultMap id="findOrderUserAndOrderDetail"
type="orders" extends="OrderUserResultMap"> <!--因为继承了订单关联查询用户的resultMap定义
所以不用再定义这两部分的,只需要定义订单详情即可 --> <!--定义订单详情 一个订单关联查询出了多条明细,要使用collection进行映射
collection:对关联查询到多条记录映射到集合对象中 property:将关联查询到多条记录映射到Orders类的哪个属性
ofType:指定映射到list集合所对应的pojo的类型 --> <collection property="orderdetails"
ofType="Orderdetail"> <!--column:查询列的唯一标识,从sql语句得出使用了别名,是为了和用户字段区分
property:对应pojo的哪个字段 --> <id column="orderdetail_id" property="id"/> <result
column="orders_id" property="ordersId"/> <result column="items_id"
property="itemsId"/> <result column="items_num" property="itemsNum"/>
</collection> </resultMap> <select id="findOrderUserAndOrderDetail"
resultMap="findOrderUserAndOrderDetail"> SELECT orders.*, USER.username,
USER.sex, USER.address, orderdetail.id orderdetail_id, orderdetail.items_id,
orderdetail.items_num, orderdetail.orders_id FROM orders, USER, orderdetail
WHERE orders.user_id = user.id AND orderdetail.orders_id=orders.id </select>
6.编写mapper接口

7.编写测试类

8.查看测试结果

展开来看看具体

<>一对多总结

可以看出,使用resultMap可以轻松的将关联查询数据映射到一个list集合中,只需要在映射类中添加相应的类型的集合,然后生成getter和setter方法,然后在resultMap配置好查询字段和pojo类的映射关系即可

<>多对多

有了上面的数据表已经一对多的查询基础,那么我们就可以实现一个多对多查询

1.实现一个查询用户的同时查询用户购买的商品,通过上面的表分析我们可以知道用户和商品之间是没有联系的,但是用户和订单有联系,订单和订单详情有联系,然后订单详情和商品有联系,那么这样是不是用户和商品之间有了间接联系呢?然后一个用户是不是可以购买多种商品,一种商品是不是也可以给多个不同的用户购买,所以他们之间是多对多关系

2.需求是要查询用户然后关联查询商品,那么就可以将最终的查询信息映射到用户表中。

3.然后在user类中添加订单属性,这样就可以把订单属性映射到这个属性上(有了订单才能关联到订单详情)

4.然后在订单中添加订单详情属性,这样就可以把订单详情映射到该属性种(有了订单详情才能关联商品)

5.最后就在订单详情中添加商品属性,把商品信息映射到这个属性上即可

6.分析上述可知,它们之间是一级一级之间联系起来的,4个类之间互相依赖形成嵌套关系,最后查询结果也是符合下图的嵌套关系的

7.编写sql查询语句

8.编写mapper.xml文件

虽然看上去非常的长,但其实理解起来并不难的,对着图的分析,最外层就是最终映射结果,然后处理好表与表之间的关系决定采用association还是collection,看好表与表之间的联系之处(外键)对应的字段名和其pojo对应的属性名,只要配好了唯一标识,普通字段就简单了
<!--定义查询用户及其购买商品信息resultMap--> <resultMap id="findUserAndItems" type="user">
<!--用户信息 查询列中的唯一标识,订单的user_id外键指向的就是用户id --> <id column="user_id"
property="id"/> <result column="username" property="username"/> <result
column="sex" property="sex"/> <result column="address" property="address"/>
<!--订单信息 一个用户对应多个订单 在用户中添加订单属性 --> <collection property="orderslist"
ofType="Orders"> <!--查出来的订单列字段名就是id,对应Orders的属性也是id,这里没有查询用户的id
故而没有重复字段名,不用设置别名--> <id column="id" property="id"/> <result column="user_id"
property="userId"/> <result column="number" property="number"/> <result
column="createtime" property="createtime"/> <result column="note"
property="note"/> <!--这里配置订单明细 在订单中添加订单明细属性 因为一个订单对应多个明细,故而采用嵌套形式 -->
<collection property="orderdetails" ofType="Orderdetail">
<!--查询列使用了别名orderdetail_id,对应集合pojo类的字段为id 是为了区分订单id字段名--> <id
column="orderdetail_id" property="id"/> <result column="items_id"
property="itemsId"/> <result column="items_num" property="itemsNum"/> <result
column="orders_id" property="ordersId"/> <!--商品信息,因为一个订单明细对应一个商品,
所以在订单明细中添加商品属性 所以嵌套进订单明细中,且两者之间的关系是一对一,故而使用association--> <association
property="items" javaType="items"> <!--查询列的唯一标识,订单明细中的items_id的外键就是商品id--> <id
column="items_id" property="id"/> <result column="items_name" property="name"/>
<result column="items_detail" property="detail"/> <result column="items_price"
property="price"/> </association> </collection> </collection> </resultMap>
<!--查询用户及用户购买的商品信息--> <select id="findUserAndItems"
resultMap="findUserAndItems"> SELECT orders.*, user.username, user.sex,
user.address, orderdetail.id orderdetail_id, orderdetail.items_id,
orderdetail.items_num, orderdetail.orders_id, items.name items_name,
items.detail items_detail, items.price items_price FROM orders, user,
orderdetail, items WHERE orders.user_id = user.id AND
orderdetail.orders_id=orders.id AND orderdetail.items_id = items.id </select>
9.编写mapper接口

10.测试类

11.查看结果

通过一层一层的展开信息,我们发现是不是符合上面的包含关系啊,真神奇啊,这样就可以实现很多有趣的功能

<>总结

1.没有特殊要求时使用resultTypt

2.使用resultMap时确定好对应关系,采用association还是collection

3.注意pojo类之间的依赖关系

4.由此就可以知道mybatis比hibernate灵活太多了

高级映射就写到了这里了,毕竟是自己的学习笔记,可能不太全面,但是我个人感觉还是很好的理解了这个映射。哈哈真神奇啊

技术
©2019-2020 Toolsou All rights reserved,
css中上下左右居中的几种实现方法[CISCN 2019 初赛]Love Mathc/c++语言实现登陆界面Unity3D 人称设置(第一人称视角、第三人称视角)Fastadmin框架自定义搜索操作流程2021最新Python自动化软件测试笔试题(含答案)黑客帝国装逼的代码雨mysql数据库设置字符集配置修改my.ini文件(windows)python之panda模块1Python学习笔记:基础+进阶10道练习题