MyBatis(二)——关联查询(转载)

文章目录

  1. 搭建环境
  2. 一对一
    2.1 使用ResultType
    2.2 使用ResultMap
  3. 一对多
  4. 多对多
  5. 搭建环境
    本文以用户User、订单Order、角色Role来进行描述mybatis中的关联查询

用户和订单之间是一对多的关系,一个用户可以有多个订单。订单和用户之间是多对一的关系,多个订单可以属于同一个用户。用户和角色之间是多对多的关系,一个用户可以有多个角色,多个角色也可以只属于一个用户。

Order——User
在这里插入图片描述
User——Role
在这里插入图片描述

建表语句

创建User表
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=28 DEFAULT CHARSET=utf8;

1
2
3
4
5
6
7
8
9
在这里插入图片描述

创建Order表
CREATE TABLE order (
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_order_id FOREIGN KEY (user_id) REFERENCES user (id) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
1
2
3
4
5
6
7
8
9
10
在这里插入图片描述

注意,用户表和订单表之间使用外键连接的,外键要建在多的一方,因为,如果建在一的一方,那么主键要一个字段要存多个值了,不利于维护和操作,所以,mysql中,外键都是要建在多的一方。

创建Role表
create table role(
id int (11) not null AUTO_INCREMENT,
name varchar(32) not null,
primary key (`id))
1
2
3
4
在这里插入图片描述
(数据可能不太恰当,只要能说明问题就行【捂脸】)

User表和Role表是多对多关系,相当于是两个多对一,所以,建立一张辅助表user_role

create table role_user(
id int(10) not null auto_increment,
u_id int(10) not null,
r_id int(10) not null,
PRIMARY key(id),
CONSTRAINT user_id FOREIGN KEY(u_id) REFERENCES user(id),
CONSTRAINT role_id FOREIGN key(r_id) REFERENCES role(id)
)

1
2
3
4
5
6
7
8
9
在这里插入图片描述

实体类

User
public class User {
private Integer id;
private String username;
private String sex;
private Date birthday;
private String address;
//…(getter、setter)
}
1
2
3
4
5
6
7
8
Order
public class Order {
private Integer id;

private Integer userId;

private String number;

private Date createtime;

private String note;
//getter、setter方法

}
1
2
3
4
5
6
7
8
9
10
11
12
Role
public class Role {

private Integer id;
private String name;
//getter、setter方法

}
1
2
3
4
5
6
2. 一对一
一个订单只属于一个用户,从订单的角度看是一对一关系。

一对一映射,有两种方式:

2.1 使用ResultType
新建OrderUser的pojo,继承自Order(这里继承User、Order类都一样,只要这个Pojo包含User、Order的所有属性即可)。

//一对一关联查询的时候,使用的新的实体类,作为返回值类型
public class OrderUser extends Order {
private Integer id;
private String username;
private String sex;
private Date birthday;
private String address;
//getter、setter方法
}
1
2
3
4
5
6
7
8
9
修改order的映射文件,新增查询方法getOrderUser

select o.id, o.user_id userId, o.number, o.createtime, o.note, u.username, u.address from `order` o left join `user` u on o.user_id = u.id; 1 2 3 4 5 6 7 8 9 10 11 12 测试

@Test //测试使用resultType的一对一关联查询
//查询订单的用户信息
public void testQueryOrderUser() {
SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();
SqlSession sqlSession = sqlSessionFactory.openSession();
OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);
List list = orderMapper.queryOrderUser();
for (OrderUser orderUser : list) {
System.out.println(orderUser);
}
}
1
2
3
4
5
6
7
8
9
10
11
结果
在这里插入图片描述

2.2 使用ResultMap
resultMap用于结果映射,使用这种方式,就是手动的将查询结果进行映射

改造Order的pojo,在Order类中添加一个User属性

//添加User属性
private User user;
//并生成响应的getter、setter方法
1
2
3
修改Order的映射文件

 <id property="id" column="id"/>
 <!--result标签用于数据库中的字段和javaBean的绑定
 		property:javaBean中的属性名
 		column:数据库中字段名
 -->
 <result property="userId" column="user_id"/>
 <result property="number" column="number"/>
 <result property="createtime" column="createtime"/>
 <result property="note" column="note"/>

<!-- association:配置一对一关联映射
	 property:pojo中的一个对象属性,order里面的User属性名
	 javaType:pojo关联的pojo对象类型
 -->

<association property="user" javaType="user">
	<!-- id标签用于绑定主键
		 column:"表的主键字段,或者可以为查询语句中的别名字段"
		 property:"映射pojo对象的主键属性" 
	-->
	<id property="id" column="user_id"/>
	<result property="username" column="username"/>
	<result property="address" column="address"/>
</association>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 在这里插入图片描述
  1. 一对多
    一个用户,可以有多个订单,在用户的角度上,用户和订单是一对多的关系

改造User的pojo,一个User可以有多个Order,可以在User中建一个只能装Order的List

//配置一对多关系映射
private List orders;
//生成响应的getter、setter方法
1
2
3
修改User的映射文件

<!-- 一对多关联映射配置,注意是oftype,
	 property:pojo的集合属性名
	 ofType:集合中的pojo对象类型
-->

<collection property="orders" ofType="order">
	
	<!-- id标签用于绑定主键
  column:"表的主键字段,或者可以为查询语句中的别名字段"
  property:"映射pojo对象的主键属性" 
	-->
	
	<id property="id" column="oid"/>
	<result property="userId" column="user_id"/>
	<result property="number" column="number"/>
	<result property="createtime" column="createtime"/>
	<result property="note" column="note"/>
</collection>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 测试

@Test //测试一对多关联查询
public void testSelectUserOrderResultMap(){
SqlSessionFactory sessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();
SqlSession sqlSession = sessionFactory.openSession(true);
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List list = userMapper.selectUserOrderResultMap();
for (User user : list) {
System.out.println(user);
for (Order order : user.getOrders()) {
System.out.println(" 订单有:" + order);
}

}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
结果
在这里插入图片描述

  1. 多对多
    一个用户可以有多个角色,一个角色也可以有多个用户,多对多用户,可以拆分为两个一对多,只看用户的话,一个用户可以有多个角色,只看角色的话,一个角色可以有多个用户。或者,你不用在意他是多对多,只需要根据查询的的结果配置相应的结果映射即可。

比如,根据id查询用户的信息以及角色信息

首先,在 User 中添加一个List roles集合属性

//配置多对多关系映射
private List roles;
//生成响应的getter、setter方法
1
2
3
修改User的映射文件

<collection property="roles" ofType="role">
	<id property="r_id" column="r_id"></id>
	<result property="name" column="name"></result>
</collection>
select u.id,u.username,u.birthday,u.sex,u.address,r.name from user u left join role_user ru on u.id=ru.u_id left join role r on r.r_id=ru.r_id where u.id=#{id} 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 测试

@Test //测试多对多
public void testSelectUserRoleById() {
SqlSessionFactory sessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();
SqlSession sqlSession = sessionFactory.openSession(true);
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.selectUserRoleById(2);
System.out.println(user);
}
1
2
3
4
5
6
7
8
结果
在这里插入图片描述
如果是查询角色对应的用户和上述过程一样,这里就不叙述了。

另外,保存用户的时候,要手动维护第三张表(可以使用foreach标签进行批量插入),否则用户表和角色表无法关联。

小结

关联-association
集合-collection
所以association是用于一对一和多对一,而collection是用于一对多的关系
JavaType和ofType都是用来指定对象类型的
JavaType是用来指定pojo中属性的类型
ofType指定的是映射到list集合属性中pojo的类型。
注意说明:

1、保证SQL的可读性,尽量通俗易懂

2、根据实际要求,尽量编写性能更高的SQL语句

3、注意属性名和字段不一致的问题

4、注意一对多和多对一 中:字段和属性对应的问题

原文链接:https://blog.youkuaiyun.com/weixin_43691723/article/details/108130141?utm_medium=distribute.pc_feed.none-task-blog-personrec_tag-5.nonecase&depth_1-utm_source=distribute.pc_feed.none-task-blog-personrec_tag-5.nonecase&request_id=5f4399140388ae0b5643c820

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值