Mybatis关系映射

一、一对一关系映射

使用resultType+包装类实现

  1、假设问题背景是要求在某一个购物平台的后台程序中添加一个这样的功能:查询某个订单的信息和下该订单的用户信息。首先我们可以知道,一般这样的平台上面,某一笔订单只属于某一个用户,从这个角度来看,可以作为一对一的参考模型

  ①首先创建数据表user(用户表)

CREATE TABLE `user` (
  `uid` INT(11) NOT NULL AUTO_INCREMENT,
  `username` VARCHAR(255) DEFAULT NULL,
  `password` VARCHAR(255) DEFAULT NULL,
  `sex` VARCHAR(255) DEFAULT NULL,
  PRIMARY KEY (`uid`)
) ENGINE=INNODB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8

  创建orders表(所用的订单表)

CREATE TABLE `orders` (
  `oid` INT(11) NOT NULL AUTO_INCREMENT,
  `total` DOUBLE DEFAULT NULL,
  `ordertime` DATETIME DEFAULT NULL,
  `name` VARCHAR(20) DEFAULT NULL,
  `uid` INT(11) DEFAULT NULL,
  PRIMARY KEY (`oid`),
  KEY `FKC3DF62E5AA3D9C7` (`uid`),
  CONSTRAINT `FKC3DF62E5AA3D9C7` FOREIGN KEY (`uid`) REFERENCES `user` (`uid`)
) ENGINE=INNODB AUTO_INCREMENT=9004 DEFAULT CHARSET=utf8

  如下图所示:

  ②创建User和Order的实体类

 1 package cn.mybatis.po;
 2
 3 public class User {
 4     private int uid;
 5     private String username;
 6     private String password;
 7     private String address;
 8     private String sex;
 9
10     public int getUid() {
11         return uid;
12     }
13
14     public void setUid(int uid) {
15         this.uid = uid;
16     }
17
18     public String getUsername() {
19         return username;
20     }
21
22     public String getPassword() {
23         return password;
24     }
25
26     public String getAddress() {
27         return address;
28     }
29
30     public String getSex() {
31         return sex;
32     }
33
34     public void setUsername(String username) {
35         this.username = username;
36     }
37
38     public void setPassword(String password) {
39         this.password = password;
40     }
41
42     public void setAddress(String address) {
43         this.address = address;
44     }
45
46     public void setSex(String sex) {
47         this.sex = sex;
48     }
49
50     public User(String username, String password, String address, String sex) {
51         this.username = username;
52         this.password = password;
53         this.address = address;
54         this.sex = sex;
55     }
56
57     public User() {
58     }
59
60     @Override
61     public String toString() {
62         return "User{" +
63                 "uid=" + uid +
64                 ", username=‘" + username + ‘\‘‘ +
65                 ", password=‘" + password + ‘\‘‘ +
66                 ", address=‘" + address + ‘\‘‘ +
67                 ", sex=‘" + sex + ‘\‘‘ +
68                 ‘}‘;
69     }
70 }

User类

 1 package cn.mybatis.po;
 2
 3 import java.util.Date;
 4
 5 public class Order {
 6
 7     private int oid;
 8     private double total;
 9     private Date ordettime;
10     private String name;
11
12     public int getOid() {
13         return oid;
14     }
15
16     public void setOid(int oid) {
17         this.oid = oid;
18     }
19
20     public double getTotal() {
21         return total;
22     }
23
24     public void setTotal(double total) {
25         this.total = total;
26     }
27
28     public Date getOrdettime() {
29         return ordettime;
30     }
31
32     public void setOrdettime(Date ordettime) {
33         this.ordettime = ordettime;
34     }
35
36     public String getName() {
37         return name;
38     }
39
40     public void setName(String name) {
41         this.name = name;
42     }
43
44     @Override
45     public String toString() {
46         return "Order{" +
47                 "oid=" + oid +
48                 ", total=" + total +
49                 ", ordettime=" + ordettime +
50                 ", name=‘" + name + ‘\‘‘ +
51                 ‘}‘;
52     }
53 }

Order类

  ③用于需要同时查询User和Order的信息,所以需要用到上一篇中讲到的POJO输出映射类型。具体来说就是,需要自定义一个OrderPoJo,其中包含我们要查询的Order和User信息,定义的OrderPoJo类型如下(这里我们可以使用继承的方式,如果我们查询结果中哪一个类的要查询结果多就继承该类,可以简便包装类的编写)

 1 package cn.mybatis.po;
 2
 3 public class OrderPoJo extends Order{
 4
 5     private String username;
 6     private String address;
 7     private String sex;
 8
 9     public String getUsername() {
10         return username;
11     }
12
13     public void setUsername(String username) {
14         this.username = username;
15     }
16
17     public String getAddress() {
18         return address;
19     }
20
21     public void setAddress(String address) {
22         this.address = address;
23     }
24
25     public String getSex() {
26         return sex;
27     }
28
29     public void setSex(String sex) {
30         this.sex = sex;
31     }
32
33     @Override
34     public String toString() {
35         return "OrderPoJo{" +
36                 super.toString() +
37                 "username=‘" + username + ‘\‘‘ +
38                 ", address=‘" + address + ‘\‘‘ +
39                 ", sex=‘" + sex + ‘\‘‘ +
40                 ‘}‘;
41     }
42 }

  ④编写好对应的实体类和包装类之后就开始写,mapper配置文件和mapper.java。mapper配置文件中我们只需要根据问题背景写好相应的Sql语句就好

  这是编写好Sql的Mapper配置文件

 1 <?xml version="1.0" encoding="UTF-8" ?>
 2 <!DOCTYPE mapper
 3         PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 4         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 5 <!--mapper为根元素,namespace指定了命名空间-->
 6 <mapper namespace="cn.mybatis.mapper.OrderMapper">
 7
 8     <select id="findOrderAndUser" parameterType="int" resultType="orderPoJo">
 9         SELECT orders.*,
10                 user.username,user.sex,user.address
11                 FROM orders,USER
12                 WHERE oid = #{id} AND user.uid = orders.uid
13     </select>
14
15 </mapper>

  下面是mapper接口中的一个方法,由于我们只需要完成这一个问题,所以OrderMapper接口也比较简单

  

  ⑤编写好所有的文件后,使用Junit来测试文件

 1 package cn.mybatis.mapper;
 2
 3
 4 import cn.mybatis.po.OrderPoJo;
 5 import org.apache.ibatis.io.Resources;
 6 import org.apache.ibatis.session.SqlSession;
 7 import org.apache.ibatis.session.SqlSessionFactory;
 8 import org.apache.ibatis.session.SqlSessionFactoryBuilder;
 9 import org.junit.Before;
10 import org.junit.Test;
11
12 import java.io.InputStream;
13
14 public class OrderMapperTest {
15
16     private SqlSessionFactory sqlSessionFactory;
17
18     @Before
19     public void setUp() throws Exception {
20         InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
21         sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
22     }
23
24     @Test
25     public void testFindOrderAndUser() throws Exception {
26         SqlSession sqlSession = sqlSessionFactory.openSession();
27         OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);
28
29         OrderPoJo orderPoJo = orderMapper.findOrderAndUser(3);
30
31         System.out.println(orderPoJo);
32
33         sqlSession.close();
34
35     }
36
37 }

  ⑥我们来通过日志分析一下结果:最终能够按照既定的Sql查询出响应的结果

使用resultMap在配置文件中实现

  1、我们使用resultMap来进行测试的时候,首先需要注意的是,由于没有自定义包装类型,所以需要在原始的Order中添加User类型的属性,保证可以在Mapper配置文件中将查询到的User属性配置到user中,从而得到关联查询结果

 1 package cn.mybatis.po;
 2
 3 import java.util.Date;
 4
 5 public class Order {
 6
 7     private int oid;
 8     private double total;
 9     private Date ordertime;
10     private String name;
11     private User user;
12
13     public int getOid() {
14         return oid;
15     }
16
17     public void setOid(int oid) {
18         this.oid = oid;
19     }
20
21     public double getTotal() {
22         return total;
23     }
24
25     public void setTotal(double total) {
26         this.total = total;
27     }
28
29     public Date getOrdertime() {
30         return ordertime;
31     }
32
33     public void setOrdertime(Date ordertime) {
34         this.ordertime = ordertime;
35     }
36
37     public String getName() {
38         return name;
39     }
40
41     public User getUser() {
42         return user;
43     }
44
45     public void setUser(User user) {
46         this.user = user;
47     }
48
49     public void setName(String name) {
50         this.name = name;
51     }
52
53     @Override
54     public String toString() {
55         return "Order{" +
56                 "oid=" + oid +
57                 ", total=" + total +
58                 ", ordertime=" + ordertime +
59                 ", name=‘" + name + ‘\‘‘ +
60                 ", user=" + user +
61                 ‘}‘;
62     }
63 }

  2、相关类和上面的内容一样,我们使用resultMap来实现,显然需要在Mapper中配置resultMap

 1     <!--
 2         订单关联User的查询resultMap
 3         将查询的结果全部映射到Order类中
 4     -->
 5     <resultMap id="OrderResultMap" type="cn.mybatis.po.Order">
 6         <!--配置映射订单-->
 7         <id column="oid" property="oid"></id>
 8         <result column="total" property="total"></result>
 9         <result column="ordertime" property="ordertime"></result>
10         <result column="name" property="name"></result>
11
12         <!--配置关联用户信息-->
13         <!--
14             association:用于映射关联查询单个对象的信息
15             property:用于设置将关联信息映射到Order的哪个属性中
16             -->
17         <association property="user" javaType="cn.mybatis.po.User">
18             <id column="uid" property="uid"></id>
19             <result column="username" property="username"></result>
20             <result column="address" property="address"></result>
21             <result column="sex" property="sex"></result>
22         </association>
23     </resultMap>

  3、然后在Mapper配置文件中使用resultMap类型的statment

    <select id="findOrderAndUserByResultMap" parameterType="int" resultMap="OrderResultMap">
        SELECT orders.*,
                user.username,user.sex,user.address
                FROM orders,USER
                WHERE oid = #{id} AND user.uid = orders.uid
    </select>

  4、结果同使用resultType的结果一样

二、一对多关系映射

   1、我们先分析一下orderitem和orders两张数据表的关系,我们能够想到一条订单中包含许多详细的订单条目信息,所以简单的得到下面的关系

  

  2、在上面的基础上,我们再创建一张orderitem数据表

CREATE TABLE `orderitem` (
  `itemid` INT(11) NOT NULL AUTO_INCREMENT,
  `count` INT(11) DEFAULT NULL,
  `subtotal` DOUBLE DEFAULT NULL,
  `pid` INT(11) DEFAULT NULL,
  `oid` INT(11) DEFAULT NULL,
  PRIMARY KEY (`itemid`),
  KEY  (`oid`),
  KEY  (`pid`),
  KEY  (`oid`),
  FOREIGN KEY (`oid`) REFERENCES `orders` (`oid`),
  FOREIGN KEY (`pid`) REFERENCES `product` (`pid`)
) ENGINE=INNODB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8

  3、我们再创建相应的实体类orderitem

 1 package cn.mybatis.po;
 2
 3 public class OrderItem {
 4
 5     private int itemid;
 6     private int count;
 7     private double subtotal;
 8     private int pid;
 9
10     public int getItemid() {
11         return itemid;
12     }
13
14     public void setItemid(int itemid) {
15         this.itemid = itemid;
16     }
17
18     public int getCount() {
19         return count;
20     }
21
22     public void setCount(int count) {
23         this.count = count;
24     }
25
26     public double getSubtotal() {
27         return subtotal;
28     }
29
30     public void setSubtotal(double subtotal) {
31         this.subtotal = subtotal;
32     }
33
34     public int getPid() {
35         return pid;
36     }
37
38     public void setPid(int pid) {
39         this.pid = pid;
40     }
41
42     @Override
43     public String toString() {
44         return "OrderItem{" +
45                 "itemid=" + itemid +
46                 ", count=" + count +
47                 ", subtotal=" + subtotal +
48                 ", pid=" + pid +
49                 ‘}‘;
50     }
51 }

orderitem实体类

  4、类似于上面讲到的使用resultMap的方式,我们在Order中添加上orderitem这一属性,作用就是维护Order和Orderitem的关联关系

 1 package cn.mybatis.po;
 2
 3 import java.util.Date;
 4 import java.util.List;
 5
 6 public class Order {
 7
 8     private int oid;
 9     private double total;
10     private Date ordertime;
11     private String name;
12     private User user;
13
14     private List<OrderItem> orderItems;
15
16     public int getOid() {
17         return oid;
18     }
19
20     public void setOid(int oid) {
21         this.oid = oid;
22     }
23
24     public double getTotal() {
25         return total;
26     }
27
28     public void setTotal(double total) {
29         this.total = total;
30     }
31
32     public Date getOrdertime() {
33         return ordertime;
34     }
35
36     public void setOrdertime(Date ordertime) {
37         this.ordertime = ordertime;
38     }
39
40     public String getName() {
41         return name;
42     }
43
44     public User getUser() {
45         return user;
46     }
47
48     public void setUser(User user) {
49         this.user = user;
50     }
51
52     public void setName(String name) {
53         this.name = name;
54     }
55
56     public List<OrderItem> getOrderItems() {
57         return orderItems;
58     }
59
60     public void setOrderItems(List<OrderItem> orderItems) {
61         this.orderItems = orderItems;
62     }
63
64     @Override
65     public String toString() {
66         return "Order{" +
67                 "oid=" + oid +
68                 ", total=" + total +
69                 ", ordertime=" + ordertime +
70                 ", name=‘" + name + ‘\‘‘ +
71                 ", user=" + user +
72                 ", orderItems=" + orderItems +
73                 ‘}‘;
74     }
75 }

修改后的Order类

  5、我们先配置Mapper文件。使用collection配置实体类中的List属性(List<OrderItem>)

    <!--查询Order和OrderItem的配置(一对多关系查询配置)-->
    <resultMap id="OrderAndOrderItemByResultMap" type="cn.mybatis.po.Order" extends="OrderResultMap">
        <!--使用extends,可以将某一段resultMap继承过来-->
        <!--OrderItem信息-->
        <!--collections:将查询到的多条信息映射到集合中
            property:将查询到的多条记录映射到Order中的相应属性中(orderItems)
            ofType:指的是要映射的集合中的JavaType-->
        <collection property="orderItems" ofType="cn.mybatis.po.OrderItem">
            <id column="itemid" property="itemid"></id>
            <result column="count" property="count"></result>
            <result column="subtotal" property="subtotal"></result>
        </collection>
    </resultMap>

  6、然后将上面配置的resultMap加入到statment中

    <select id="findOrderAndOrderItemByResultMap" parameterType="int" resultMap="OrderAndOrderItemByResultMap">
        SELECT orders.*,
            user.username,
            user.sex,
            user.address,
            orderitem.itemid,
            orderitem.count,
            orderitem.subtotal
            FROM
            orders,
            USER,
            orderitem
            WHERE orders.oid = #{id} AND user.uid = orders.uid AND orderitem.oid = orders.oid
    </select>

  7、然后在Mapper接口中添加测试方法

    //一对多关系测试
    public Order findOrderAndOrderItemByResultMap(int id) throws Exception;

  8、将查询的结果进行输出可以发现能够正常查询出想要的结果

Order{oid=2, total=32.0, ordertime=Thu Dec 26 21:47:04 CST 2019, name=‘Lucy‘, user=User{uid=2, username=‘Rose‘, password=‘null‘, address=‘武汉市‘, sex=‘women‘}, orderItems=[OrderItem{itemid=2, count=21, subtotal=32.0, pid=0}, OrderItem{itemid=4, count=32, subtotal=54.0, pid=0}]}

 

原文地址:https://www.cnblogs.com/fsmly/p/10339619.html

时间: 2024-08-06 11:41:04

Mybatis关系映射的相关文章

mybatis关系映射之一对多和多对一

一. 简介: 本实例使用顾客和订单的例子做说明: 一个顾客可以有多个订单, 一个订单只对应一个顾客 二. 例子: 1. 代码结构图: 2. 建表语句: CREATE DATABASE test; USE test; CREATE TABLE person( personId VARCHAR(36) PRIMARY KEY, personName VARCHAR(64), personAddress VARCHAR(128), personTel VARCHAR(11) ); CREATE TAB

mybatis 关系映射

一:订单商品数据模型 1.数据库执行脚本 创建数据库表代码: 1 CREATE TABLE items ( 2 id INT NOT NULL AUTO_INCREMENT, 3 itemsname VARCHAR(32) NOT NULL COMMENT '商品名称', 4 price FLOAT(10,1) NOT NULL COMMENT '商品定价', 5 detail TEXT COMMENT '商品描述', 6 pic VARCHAR(64) DEFAULT NULL COMMENT

Mybatis框架中实现一对多关系映射

学习过Hibernate框架的伙伴们很容易就能简单的配置各种映射关系(Hibernate框架的映射关系在我的blogs中也有详细的讲解),但是在Mybatis框架中我们又如何去实现 一对多的关系映射呢? 其实很简单 首先我们照常先准备前期的环境(具体解释请  参考初识Mybatis进行增.删.改.查 blogs )这里我就直接上代码了 主配置文件:Configuration.xml <?xml version="1.0" encoding="UTF-8" ?&

mybatis中树形结构的bean的关系映射

最近用mybatis写一个小程序,涉及到树形结构的关系映射,比如一个分类,本身具有多对一的关系,那么它是如何映射呢?直接贴代码: Cate.java @Table(name="cate") public class Cate extends AbstractModel { /** * */ private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy=GenerationType.IDENTI

MyBatis的对象关系映射---一对多N+1策略★★★★★

在实际开发中,一个业务可能涉及到多个数据表的查询,那么多表查询就涉及连接查询(等值连接), 等值连接 表与表之间有一个外键关键,但是程序中最终获取的表封装的对象, 对象与对象之间是没有外键关系的,对象和对象之间只有依赖关系: 对象之间关系主要是四种: 一对一 关系一个人对应身份证id,一个QQ号对应一个QQ空间 一对多 关系 一个部门对应多个员工 多对一 关系 多个员工对应一个部门 多对多 关系 多个学生对应多个老师,多个学生对应多个课程 什么关系应该从哪个对象作为中心点来看 一对多, 以one

mybatis 一对一,一对多,多对多关系映射查询操作

定义两个类(对应数据库内两张表) User ,Account,每个Account属于一个User User类 及其 对应的IUserDao package com.itheima.domain; import java.io.Serializable; import java.util.Date; import java.util.List; public class User implements Serializable { private Integer id; private Strin

mybatis中一对一关系映射

一对一关系中普通的配置方式 一.多表连接查询语句: <select id="selectStudentWithAddress" parameterType="int" resultMap="StudentWithAddressResult"> select s.stud_id, s.name, s.email,s.dob,s.phone, a.addr_id, a.street, a.city, a.state, a.zip,a.co

170905-MyBatis中的关系映射

===关系映射=== 参考文档复习:1对1,1对多,多对多 1.映射(多)对一.(一)对一的关联关系 1).使用列的别名 ①.若不关联数据表,则可以得到关联对象的id属性 ②.若还希望得到关联对象的其它属性.则必须关联其它的数据表 1.创建表: 员工表: DROP TABLE IF EXISTS `tbl_employee`; CREATE TABLE `tbl_employee` ( `id` int(11) NOT NULL AUTO_INCREMENT, `user_name` varch

六 mybatis高级映射(一对一,一对多,多对多)

1  订单商品数据模型 以订单商品数据为模型,来对mybaits高级关系映射进行学习. 1.1     数据模型分析思路 1.每张表记录的数据内容 分模块对每张表记录的内容进行熟悉,相当 于你学习系统 需求(功能)的过程. 2.每张表重要的字段设置 非空字段.外键字段 3.数据库级别表与表之间的关系 外键关系 4.表与表之间的业务关系 在分析表与表之间的业务关系时一定要建立 在某个业务意义基础上去分析. 1.2     数据模型分析 用户表user: 记录了购买商品的用户信息 订单表:order