Mybatis多表关系

Mybatis 多表关系

mybatis 中多表关联,主要修改 mapper.xml 文件和 eitity 实体。
mapper.xml 文件中通过 resultmap 配置返回映射,eitity 实体中通过对象引用定义关系。
spring-mybatis.xml 文件与 pom.xml 文件与spring-mybatis中相同,选择其中第一种整合方式。

1、数据库执行脚本

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for item
-- ----------------------------
DROP TABLE IF EXISTS `item`;
CREATE TABLE `item` (
`itemid` int(11) NOT NULL AUTO_INCREMENT,
`itemname` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
PRIMARY KEY (`itemid`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of item
-- ----------------------------
INSERT INTO `item` VALUES (1, '里斯');
INSERT INTO `item` VALUES (2, '嗡嗡嗡');
INSERT INTO `item` VALUES (3, '迭代');
-- ----------------------------
-- Table structure for order
-- ----------------------------
DROP TABLE IF EXISTS `order`;
CREATE TABLE `order` (
`orderid` int(11) NOT NULL,
`userid` int(11) NULL DEFAULT NULL,
PRIMARY KEY (`orderid`) USING BTREE,
INDEX `userid`(`userid`) USING BTREE,
CONSTRAINT `userid` FOREIGN KEY (`userid`) REFERENCES `user` (`userid`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of order
-- ----------------------------
INSERT INTO `order` VALUES (1, 1);
-- ----------------------------
-- Table structure for orderitem
-- ----------------------------
DROP TABLE IF EXISTS `orderitem`;
CREATE TABLE `orderitem` (
`orderitemid` int(11) NOT NULL,
`orderid` int(11) NULL DEFAULT NULL,
`itemid` int(11) NULL DEFAULT NULL,
PRIMARY KEY (`orderitemid`) USING BTREE,
INDEX `orderid`(`orderid`) USING BTREE,
INDEX `itemid`(`itemid`) USING BTREE,
CONSTRAINT `itemid` FOREIGN KEY (`itemid`) REFERENCES `item` (`itemid`) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT `orderid` FOREIGN KEY (`orderid`) REFERENCES `order` (`orderid`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of orderitem
-- ----------------------------
INSERT INTO `orderitem` VALUES (1, 1, 1);
INSERT INTO `orderitem` VALUES (2, 1, 2);
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`userid` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
PRIMARY KEY (`userid`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, 'lin');
INSERT INTO `user` VALUES (2, '苏');
SET FOREIGN_KEY_CHECKS = 1;

2、数据模型分析,


用户表:user,记录了用户信息。
订单表:order,记录了用户的订单信息。
订单项表:orderitem,记录订单中,每个商品项的购买情况。
商品表:item,记录了商品信息。

2.1、表与表之间业务分析:

user 与 orer:
user—>order:一个用户可以创建多个订单
order—>user:一个订单只属于一个用户
order 与 orderitem:
order—>orderitem:一个订单包含多个订单项
orderitem—>order:一个订单项属于一个订单
orderitem 与 item:
orderitem—>item:一个订单项包含一个商品
item—>orderitem:一个商品可以属于多个订单项
user 与 item:
user—>item:一个用户可以购买多个商品
item—>user:一个商品被多个用户购买
画出图:

3、实体类

1、user.java

1
2
3
4
5
public class User {
private Integer userId;
private String userName;
// 外键引用,一个用户可以创建多个订单 private List<Order> orders;
}

2、order.java

1
2
3
4
5
public class Order {
private Integer orderId;
// 一个订单包含多个订单项 private List<OrderItem> orderItems;
// 一个订单属于一个用户 private User user;
}

3、orderitem.java

1
2
3
4
5
public class OrderItem {
private Integer orderItemId;
// 一个订单项属于一个订单 private Order order;
// 一个订单项包含一个商品 private Item item;
}

4、item.java

1
2
3
4
public class Item {
private Integer itemId;
private String itemName;
}

4、Service 及 Dao

接口 UserDao:

1
2
3
4
5
@MapperScan
public interface UserDao {
User findUserById(User user);
User findUserAndOrderById(User user);
}

接口 UserService:

1
2
3
4
public interface UserService {
User findUserById(User user);
User findUserAndOrderById(User user);
}

实现类 UserServiceImpl:

1
2
3
4
5
6
7
8
9
10
11
@Component("UserService")
public class UserServiceImpl implements UserService {
@Resource
private UserDao userdao;
public User findUserById(User user) {
return userdao.findUserById(user);
}
public User findUserAndOrderById(User user) {
return userdao.findUserAndOrderById(user);
}
}

5、多表关系

多表关系主要用于查询,mybatis 中在 mapper.xml 文件中配置 resultMap 来配置多表关系,用于返回映射。
mapper.xml 中配置了一对一,一对多,多对多关系。
userMapper.xml

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
30
31
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-// mybatis.org//DTD Mapper 3.0//EN"
" http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lin.dao.UserDao">
<!-- 配置一对一,一对多,多对一关系时,实体类中在双方加入引用,配置文件中在一方加入即可 --> <!-- collection:表示一对多关系,实体类中通常用集合表示 --> <!-- ofType:一对多中,多的实体类型 --> <!-- association:表示一对一关系,实体类中为引用 --> <!-- javaType:一对一中另一个一的实体类型 --> <!-- 将多对多关系,可以拆分成2个一对多关系,与数据库表一样 --> <!-- 用户 --> <resultMap type="com.lin.bean.User" id="UserResultMap">
<id property="userId" column="userid" />
<result property="userName" column="username" />
<!-- 一个用户拥有多个订单,表示一对多关系 --> <collection property="orders" ofType="com.lin.bean.Order" fetchType="lazy">
<!-- 订单和商品为多对多关系,将其拆分为订单,订单项,商品三张表 --> <!-- 1、一个订单包含多个订单项 - --> <!-- 2、一个订单项包含一个商品 --> <!-- 3、一个订单项属于一个订单 - --> <!-- 4、一个商品属于多个订单项(商品中不添加订单项的引用) --> <!-- 采用1和2可完成多对多的配置 --> <id property="orderId" column="orderid" />
<!-- 每个订单中包含多个订单项,一对多关系 --> <collection property="orderItems" fetchType="lazy" ofType="com.lin.bean.OrderItem">
<id property="orderItemId" column="orderitemid" />
<!-- 每个订单项包含一个商品,一对一关系 --> <!-- 嵌套结果方式 --> <!-- <association property="item" javaType="com.lin.bean.Item"> <id property="itemId"
column="itemid" /> <result property="itemName" column="itemname" /> </association> -->
<!-- 嵌套查询方式 --> <!-- column:外键字段名称:select语句参数 --> <association property="item" javaType="com.lin.bean.Item" column="itemid" select="findItemById"></association>
</collection>
</collection>
</resultMap>
<select id="findItemById" parameterType="integer" resultType="com.lin.bean.Item">
select itemid,itemname from item where itemid=#{v}
</select>
<select id="findUserAndOrderById" parameterType="com.lin.bean.User" resultMap="UserResultMap">
select
u.userid,u.username,o.orderid,or.orderitemid,i.itemid,i.itemname from
user u,`order` o,orderitem `or`,item i where o.userid=u.userid and
o.orderid=or.orderid and i.itemid=or.itemid;
</select>
<select id="findUserById" parameterType="com.lin.bean.User" resultType="com.lin.bean.User">
select * from user where userid = #{userId}
</select>
</mapper>

6、测试

1
2
3
4
5
6
7
8
9
10
11
public class App {
public static void main(String[] args) {
User user = new User();
user.setUserId(1);
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-mybatis.xml");
UserService userServie = (UserService) applicationContext.getBean("UserService");
System.out.println(userServie.findUserById(user));
System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
System.out.println(userServie.findUserAndOrderById(user));
}
}

7、结果