关联查询---Mybatis学习笔记(九)

来源:互联网 发布:期货决策软件 编辑:程序博客网 时间:2024/05/18 19:39

商品订单数据模型

这里写图片描述

注意:分析数据库表和数据库表之间的关系可以先通过数据库中的主外键关系来分析,然后通过业务中的实际的关系来分析。

1.一对一查询

需求: 
查询订单信息,关联查询创建订单的用户信息

分析需求: 
因为一个订单信息只会是一个人下的订单,所以从查询订单信息出发关联查询用户信息为一对一查询。如果从用户信息出发查询用户下的订单信息则为一对多查询,因为一个用户可以下多个订单。

1.使用ResultType实现

1.sql语句:

select orders.*,user.username,user.birthday,user.sex,user.address from orders,user where orders.user_id = user.id;
  • 1
  • 1

2.pojo类: 
将上边的sql语句的查询结果映射到pojo中,pojo必须包括所有的查询列名。 
原始的Orders.Java不能映射全部的字段,需要新创建一个pojo继承Order.java类。(一般是继承包括查询字段较多的pojo类)

orders类:

public class Orders {    private Integer id;    private Integer userId;    private String number;    private Date createtime;    private String note;    public Integer getId() {        return id;    }    public void setId(Integer id) {        this.id = id;    }    public Integer getUserId() {        return userId;    }    public void setUserId(Integer userId) {        this.userId = userId;    }    public String getNumber() {        return number;    }    public void setNumber(String number) {        this.number = number == null ? null : number.trim();    }    public Date getCreatetime() {        return createtime;    }    public void setCreatetime(Date createtime) {        this.createtime = createtime;    }    public String getNote() {        return note;    }    public void setNote(String note) {        this.note = note == null ? null : note.trim();    }    @Override    public String toString() {        return "Orders [id=" + id + ", userId=" + userId + ", number=" + number                + ", createtime=" + createtime + ", note=" + note +  "]";    }
  • 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
  • 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

OrdersCustom.java

public class OrdersCustom extends Orders{    private String username;    private Date birthday;    private String sex;    private String address;    public Date getBirthday() {        return birthday;    }    public void setBirthday(Date birthday) {        this.birthday = birthday;    }    public String getUsername() {        return username;    }    public void setUsername(String username) {        this.username = username;    }    public String getSex() {        return sex;    }    public void setSex(String sex) {        this.sex = sex;    }    public String getAddress() {        return address;    }    public void setAddress(String address) {        this.address = address;    }    @Override    public String toString() {        return "OrdersCustom [username=" + username + ", birthday=" + birthday + ", sex=" + sex + ", address=" + address                + ", getId()=" + getId() + ", getUserId()=" + getUserId() + ", getNumber()=" + getNumber()                + ", getCreatetime()=" + getCreatetime() + ", getNote()=" + getNote() + "]";    }}
  • 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
  • 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

3.mapper.xml文件

<mapper namespace="com.huihui.mapper.OrdersCustomMapper">    <!-- 查询订单关联查询用户 -->    <select id="findOrderUser" resultType="com.huihui.pojo.OrdersCustom">        select orders.*,user.username,user.birthday,user.sex,user.address from orders,user where orders.user_id = user.id     </select></mapper>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

4.mapper接口:

public interface OrdersCustomMapper {    //查询订单关联查询用户    public List<OrdersCustom> findOrderUser() throws Exception;}
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

5.测试:

public class OrdersCustomMapperTest {    private SqlSessionFactory sqlSessionFactory;    @Before    // 此方法是运行下面的测试用例的方法之前执行的    public void setUp() throws Exception {        // 创建sqlSessionFactory        // mybatis配置文件路径        String resource = "SqlMapConfig.xml";        // 得到配置文件流        InputStream inputStream = Resources.getResourceAsStream(resource);        // 创建会话工厂,传入mybatis的配置文件信息        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);    }    @Test    public void testFindOrdersUser() throws Exception{        SqlSession sqlSession = sqlSessionFactory.openSession();        //创建代理对象        OrdersCustomMapper ordersMapperCustom = sqlSession.getMapper(OrdersCustomMapper.class);        //调用mapper的方法        List<OrdersCustom> list = ordersMapperCustom.findOrderUser();        for (OrdersCustom ordersCustom : list) {            System.out.println(ordersCustom);        }        System.out.println(list.size());        sqlSession.close();    }}
  • 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
  • 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

2.使用ResultMap实现 
1.sql语句(同ResultType实现的sql语句一样):

select orders.*,user.username,user.birthday,user.sex,user.address from orders,user where orders.user_id = user.id;
  • 1
  • 1

2.pojo类 
使用resultMap将查询的结果中的订单信息映射到Orders对象中,在orders类中添加User属性,将关联查询出来的用户信息映射到Order对象中的user属性中。 
在Orders类中加入User属性,user属性中用于存储关联查询的用户信息,因为订单关联查询用户是一对一关系,所以这里使用单个User对象存储关联查询的用户信息。

Order类:

public class Orders {    private Integer id;    private Integer userId;    private String number;    private Date createtime;    private String note;    //用户信息    private User user;    public Integer getId() {        return id;    }    public void setId(Integer id) {        this.id = id;    }    public Integer getUserId() {        return userId;    }    public void setUserId(Integer userId) {        this.userId = userId;    }    public String getNumber() {        return number;    }    public void setNumber(String number) {        this.number = number == null ? null : number.trim();    }    public Date getCreatetime() {        return createtime;    }    public void setCreatetime(Date createtime) {        this.createtime = createtime;    }    public String getNote() {        return note;    }    public void setNote(String note) {        this.note = note == null ? null : note.trim();    }    public User getUser() {        return user;    }    public void setUser(User user) {        this.user = user;    }    @Override    public String toString() {        return "Orders [id=" + id + ", userId=" + userId + ", number=" + number                + ", createtime=" + createtime + ", note=" + note + ", user="                + user +  "]";    }}
  • 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
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 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
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75

3.mapper.xml文件: 
定义ResultMap: 
需要关联查询映射的是用户信息,使用association将用户信息映射到订单对象的用户属性中。

    <!-- 订单查询关联用户的resultmap -->    <resultMap type="com.huihui.pojo.Orders" id="OrdersUserResultMap">        <!-- 配置映射的订单信息 -->        <!-- id指定查询列中的唯一标识,如果有多个列组成唯一标识,就配置多个id -->        <!-- column:订单信息的唯一标识列            property:订单信息的唯一标识列所映射到的Orders中的那个属性中             -->        <id column="id" property="id" />        <!-- result表示普通列的映射配置 -->        <result column="user_id" property="userId"/>        <result column="number" property="number"/>        <result column="createtime" property="createtime"/>        <result column="number" property="note"/>        <!-- 配置映射的关联信息 -->        <!--association:用于映射关联查询单个对象的信息  -->        <!-- property:要将关联查询的用户信息映射到Orders中的哪个属性             javaType:user属性的java类型        -->        <association property="user" javaType="com.huihui.pojo.User">        <!-- id:关联查询用户的唯一标识 -->        <!-- column:指定唯一表示用户信息的列            property:映射到user的哪个属性         -->            <id column="user_id" property="id"/>            <!-- result:普通列的映射配置 -->            <result column="username" property="username"/>            <result column="birthday" property="birthday"/>            <result column="sex" property="sex"/>            <result column="address" property="address"/>        </association>    </resultMap>
  • 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
  • 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

说明: 
association:表示进行关联查询单条记录 
property:表示关联查询的结果存储在com.huihui.pojo.Orders的user属性中 
javaType:表示关联查询的结果类型 
<id property="id" column="user_id"/>:查询结果的user_id列对应关联对象的id属性,这里是<id />表示user_id是关联查询对象的唯一标识。 
<result property="username" column="username"/>:查询结果的username列对应关联对象的username属性。

定义statement:

    <!-- 查询订单信息关联查询用户(使用ResultMap) -->    <select id="findOrderUserResultMap" resultMap="OrdersUserResultMap">        select orders.*,user.username,user.birthday,user.sex,user.address from        orders,user where orders.user_id = user.id    </select>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

4.mapper接口:

    //查询订单关联查询用户(使用ReusltMap)    public List<Orders> findOrderUserResultMap() throws Exception;
  • 1
  • 2
  • 1
  • 2

5.测试:

    @Test    public void testFindOrdersUserResultMap() throws Exception{        SqlSession sqlSession = sqlSessionFactory.openSession();        //创建代理对象        OrdersCustomMapper ordersMapperCustom = sqlSession.getMapper(OrdersCustomMapper.class);        //调用mapper的方法        List<Orders> list = ordersMapperCustom.findOrderUserResultMap();        for (Orders orders : list) {            System.out.println(orders);        }        System.out.println(list.size());        sqlSession.close();    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

3.resultType和resultMap实现一对一查询小结: 
实现一对一查询: 
定义专门的po类作为输出类型,其中定义了sql查询结果集所有的字段。此方法较为简单,企业中使用普遍。

2.一对多查询

需求: 
查询订单及订单明细的信息。 
订单与订单明细为一对多关系。

分析需求: 
查询的主表:订单表 
查询的关联表:订单明细表 
在一对一查询基础上添加订单明细表关联即可。

使用ResultMap实现:

1.sql语句:

SELECT    orders.*, USER .username,    USER .sex,    USER .address,    orderdetail.id as orderdetail_id,    orderdetail.items_id,    orderdetail.items_num,    orderdetail.orders_idFROM    orders,    USER,    orderdetailWHERE    orders.user_id = USER .idAND orderdetail.orders_id = orders.id;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

注意:这里查询出orderdetail.id as orderdetail_id, 的作用是下面mapper.xml映射文件中的collection标签中需要<id>中的唯一列。

查询结果: 
这里写图片描述 
发现结果中的红色方框中的记录是重复的,但是后边的items_id、items_num、orders_id列是不重复的。 
那么这里如果使用resultType映射上面的查询结果到pojo中的话,那么就会存在重复的信息。

解决方法:使用resultMap映射,将查询结果映射到resultMap中设置的pojo类中,并且在pojo类中添加List<Orderdetail> orderdetails 属性。那么最终会将订单信息映射到orders中,订单所对应的订单明细就会映射到orders中的orderdetail属性中。也就是说上图中的查询结果映射成的orders记录数为2条(order信息不重复),每个orders中的orderdetails属性存储了该订单所对应的订单明细。

2.pojo类: 
Orders.java类中添加如下内容:

    //订单明细    private List<Orderdetail> orderdetails;    public List<Orderdetail> getOrderdetails() {        return orderdetails;    }    public void setOrderdetails(List<Orderdetail> orderdetails) {        this.orderdetails = orderdetails;    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

注意还要重写以下toString()方法,让toString()方法打印出订单详情的信息。

3.mapper.xml映射文件:

定义ResultMap:

    <!-- 查询订单及订单明细的resultmap -->    <resultMap type="com.huihui.pojo.Orders" id="OrdersAndOrderDetailResultMap">        <!-- 订单信息 -->        <id column="id" property="id" />        <result column="user_id" property="userId" />        <result column="number" property="number" />        <result column="createtime" property="createtime" />        <result column="number" property="note" />        <!-- 用户信息 -->        <association property="user" javaType="com.huihui.pojo.User">            <id column="user_id" property="id" />            <result column="username" property="username" />            <result column="birthday" property="birthday" />            <result column="sex" property="sex" />            <result column="address" property="address" />        </association>        <!-- 订单明细信息 -->        <!-- collection:对关联查询到的多条记录映射到集合对象中 -->        <!-- property:将关联查询到多条记录映射到com.huihui.pojo.Orders中的哪个属性            ofType:指定映射到集合属性中pojo的类型         -->        <collection property="orderdetails" ofType="com.huihui.pojo.Orderdetail">            <!-- id:订单明细的唯一标识                property:将订单明细的唯一标识列映射到com.huihui.pojo.Orderdetail中的哪个属性             -->            <id column="orderdetail_id" property="id"/>            <result column="items_id" property="itemsId"/>            <result column="items_num" property="itemsNum"/>            <result column="orders_id" property="ordersId"/>        </collection>    </resultMap>
  • 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
  • 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

发现上面配置中的订单信息和用户信息之前在一对一映射(使用ResultMap)中定义ResultMap时定义的相同,那么可以使用继承(extends)之前定义的ResultMap的方式:

    <!-- 查询订单及订单明细的resultmap -->    <resultMap type="com.huihui.pojo.Orders" id="OrdersAndOrderDetailResultMap" extends="OrdersUserResultMap">        <!-- 订单信息 -->        <!-- 用户信息 -->        <!-- 订单明细信息 -->        <!-- collection:对关联查询到的多条记录映射到集合对象中 -->        <!-- property:将关联查询到多条记录映射到com.huihui.pojo.Orders中的哪个属性            ofType:指定映射到集合属性中pojo的类型         -->        <collection property="orderdetails" ofType="com.huihui.pojo.Orderdetail">            <!-- id:订单明细的唯一标识                property:将订单明细的唯一标识列映射到com.huihui.pojo.Orderdetail中的哪个属性             -->            <id column="orderdetail_id" property="id"/>            <result column="items_id" property="itemsId"/>            <result column="items_num" property="itemsNum"/>            <result column="orders_id" property="ordersId"/>        </collection>    </resultMap>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

说明: 
collection部分定义了查询订单明细信息。 
collection:表示关联查询结果集 
property=”orderdetails”:关联查询的结果集存储在com.huihui.pojo.Orders上哪个属性。 
ofType=”com.huihui.pojo.Orderdetail”:指定关联查询的结果集中的对象类型即List中的对象类型。 
<id />及<result/>的意义同一对一查询。

定义statement:

    <!-- 查询订单关联查询用户及订单明细(使用ResultMap) -->    <select id="findOrdersAndOrderDetailResultMap" resultMap="OrdersAndOrderDetailResultMap">        SELECT        orders.*, USER .username,        USER .sex,        USER .address,        orderdetail.id as 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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

4.mapper接口:

    //查询订单(关联用户)及订单明细    public List<Orders> findOrdersAndOrderDetailResultMap() throws Exception;
  • 1
  • 2
  • 1
  • 2

5.测试:

    @Test    public void testFindOrdersAndOrderDetailResultMap() throws Exception{        SqlSession sqlSession = sqlSessionFactory.openSession();        //创建代理对象        OrdersCustomMapper ordersMapperCustom = sqlSession.getMapper(OrdersCustomMapper.class);        //调用mapper的方法        List<Orders> list = ordersMapperCustom.findOrdersAndOrderDetailResultMap();        for (Orders orders : list) {            System.out.println(orders);        }        System.out.println(list.size());        sqlSession.close();    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

小结: 
mybatis使用resultMap的collection对关联查询的多条记录映射到一个list集合属性中。

如果使用resultType实现: 
将订单明细映射到orders中的orderdetails中,就需要自己手动处理(使用双重循环遍历去去掉重复记录,将订单明细信息存放到orderdetail中)

3.多对多查询

需求: 
查询用户及用户购买的商品信息

分析需求: 
查询的主表是:用户表 
关联表:由于用户和商品没有直接关联,通过订单和订单明细进行关联。所以关联表为:orders、orderdetail、items

1.sql语句:

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_priceFROM    orders,    USER,    orderdetail,    itemsWHERE    orders.user_id = USER .idAND orderdetail.orders_id = orders.idAND orderdetail.items_id = items.id
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

2.映射的pojo类: 
映射思路: 
将用户信息映射到user中。 
在user类中添加订单列表属性List<Orders> orderslist,将用户创建的订单映射到orderslist。 
在Orders中添加订单明细列表属性List<OrderDetail>orderdetials,将订单的明细映射到orderdetials。 
在OrderDetail中添加Items属性,将订单明细所对应的商品映射到Items

User.java类中添加以下内容:

    private List<Orders> orderslist;//订单列表    public List<Orders> getOrderslist() {        return orderslist;    }    public void setOrderslist(List<Orders> orderslist) {        this.orderslist = orderslist;    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

Orders.java类中添加以下内容:

    //订单明细    private List<Orderdetail> orderdetails;    public List<Orderdetail> getOrderdetails() {        return orderdetails;    }    public void setOrderdetails(List<Orderdetail> orderdetails) {        this.orderdetails = orderdetails;    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

Orderdetail.java类中增加以下内容:

    private Items items;//订单明细所对应的商品信息    public Items getItems() {        return items;    }    public void setItems(Items items) {        this.items = items;    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

3.mapper.xml映射文件: 
resultmap定义:

    <!-- 查询用户及购买的商品信息的resultmap -->    <resultMap type="com.huihui.pojo.User" id="UserAndItemsResultMap">        <!-- 用户信息 -->        <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="com.huihui.pojo.Orders">            <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="com.huihui.pojo.Orderdetail">                <id column="orderdetail_id" property="id"/>                <result column="items_id" property="ordersId"/>                <result column="items_num" property="itemsId"/>                <result column="orders_id" property="itemsNum"/>                <!-- 商品信息 -->                <association property="items" javaType="com.huihui.pojo.Items">                    <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>
  • 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
  • 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

定义statement:

    <!-- 查询用户及购买的商品信息,使用resultMap -->    <select id="findUserAndItemsResultMap" resultMap="UserAndItemsResultMap">        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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

4.mapper接口:

    //查询用户及与用户相关联的商品信息    public List<User> findUserAndItemsResultMap() throws Exception;
  • 1
  • 2
  • 1
  • 2

5.测试:

    @Test    public void findUserAndItemsResultMap() throws Exception{        SqlSession sqlSession = sqlSessionFactory.openSession();        //创建代理对象        OrdersCustomMapper ordersMapperCustom = sqlSession.getMapper(OrdersCustomMapper.class);        //调用mapper的方法        List<User> list = ordersMapperCustom.findUserAndItemsResultMap();        for (User users : list) {            System.out.println(users);        }        System.out.println(list.size());        sqlSession.close();    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

多对多查询总结: 
将查询用户购买的商品信息明细清单,(用户名、用户地址、购买商品名称、购买商品时间、购买商品数量)

针对上边的需求就使用resultType将查询到的记录映射到一个扩展的pojo中,很简单实现明细清单的功能。

一对多是多对多的特例,如下需求: 
查询用户购买的商品信息,用户和商品的关系是多对多关系。 
需求1: 
查询字段:用户账号、用户名称、用户性别、商品名称、商品价格(最常见) 
企业开发中常见明细列表,用户购买商品明细列表, 
使用resultType将上边查询列映射到pojo输出。

需求2: 
查询字段:用户账号、用户名称、购买商品数量、商品明细(鼠标移上显示明细) 
使用resultMap将用户购买的商品明细列表映射到user对象中。

总结: 
使用resultMap是针对那些对查询结果映射有特殊要求的功能,,比如特殊要求映射成list中包括 多个list。

ResultMap总结:

resultType: 
作用: 
将查询结果按照sql列名pojo属性名一致性映射到pojo中。 
场合: 
常见一些明细记录的展示,比如用户购买商品明细,将关联查询信息全部展示在页面时,此时可直接使用resultType将每一条记录映射到pojo中,在前端页面遍历list(list中是pojo)即可。

resultMap: 
使用association和collection完成一对一和一对多高级映射(对结果有特殊的映射要求)。

association: 
作用: 
将关联查询信息映射到一个pojo对象中。 
场合: 
为了方便查询关联信息可以使用association将关联订单信息映射为用户对象的pojo属性中,比如:查询订单及关联用户信息。 
使用resultType无法将查询结果映射到pojo对象的pojo属性中,根据对结果集查询遍历的需要选择使用resultType还是resultMap。

collection: 
作用: 
将关联查询信息映射到一个list集合中。 
场合: 
为了方便查询遍历关联信息可以使用collection将关联信息映射到list集合中,比如:查询用户权限范围模块及模块下的菜单,可使用collection将模块映射到模块list中,将菜单列表映射到模块对象的菜单list属性中,这样的作的目的也是方便对查询结果集进行遍历查询。 
如果使用resultType无法将查询结果映射到list集合中。

延迟加载

什么是延迟加载?

延迟加载:先从单表查询、需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快。

resultMap可以实现高级映射(使用association、collection实现一对一及一对多映射),association、collection具备延迟加载功能。 
需求: 
如果查询订单并且关联查询用户信息。如果先查询订单信息即可满足要求,当我们需要查询用户信息时再查询用户信息。把对用户信息的按需去查询就是延迟加载。

需求: 
查询订单并且关联查询用户信息

1.pojo类 
Orders.java类中增加以下内容:

    private User user;// 用户信息    public User getUser() {        return user;    }    public void setUser(User user) {        this.user = user;    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

2.mapper.xml映射文件:

需要定义两个mapper的方法对应的statement。 
1、只查询订单信息

SELECT * FROM orders
  • 1
  • 1

在查询订单的statement中使用association去延迟加载(执行)下边的satatement(关联查询用户信息)

    <!-- 查询订单关联查询用户信息,用户信息需要延迟加载 -->    <select id="findOrdersUserLazyLoading" resultMap="OrdersUserLazyLoadingResultMap">        select * from orders    </select>
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

2、关联查询用户信息 
通过上边查询到的订单信息中user_id去关联查询用户信息 
使用UserMapper.xml中的findUserById

    <select id="findUserById" parameterType="int" resultType="com.huihui.pojo.User">        select * from User where id = #{value}    </select>
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

上边先去执行findOrdersUserLazyLoading,当需要去查询用户的时候再去执行findUserById,通过resultMap的定义将延迟加载执行配置起来

3、定义延迟加载的ResultMap 
使用association中的select指定延迟加载去执行的statement的id。

    <!-- 延迟加载用户信息的resultmap -->    <resultMap type="com.huihui.pojo.Orders" id="OrdersUserLazyLoadingResultMap">        <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" />        <!-- 实现对用户信息进行延迟加载 -->        <!-- select:指定延迟加载需要执行的statement的id(是根据user_id查询用户信息的statement)             column:关联查询的列。订单信息中关联用户信息查询的列,这里是user_id        -->        <association property="user" javaType="com.huihui.pojo.User" select="findUserById" column="user_id"></association>    </resultMap>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

说明: 
association: 
select=”findUserById”:指定关联查询sql为findUserById 
column=”user_id”:关联查询时将users_id列的值传入findUserById 
最后将关联查询结果映射至com.huihui.pojo.User。

3.mapper接口:

    //查询订单关联查询用户(用户信息是延迟加载)    public List<Orders> findOrdersUserLazyLoading() throws Exception;
  • 1
  • 2
  • 1
  • 2

3.测试:

执行过程: 
1、执行上边mapper方法(findOrdersUserLazyLoading),内部去调用com.huihui.mapper.OrdersCustomMapper中的findOrdersUserLazyLoading只查询orders信息(单表)。 
2、在程序中去遍历上一步骤查询出的List<Orders>,当我们调用Orders中的getUser方法时,开始进行延迟加载。 
3、延迟加载,去调用UserMapper.xml中findUserbyId这个方法获取用户信息。

延迟加载配置: 
mybatis默认没有开启延迟加载,需要在SqlMapConfig.xml中setting配置。 
在mybatis核心配置文件中配置:lazyLoadingEnabled、aggressiveLazyLoading

设置项描述允许值默认值lazyLoadingEnabled全局性设置懒加载。如果设为‘false’,则所有相关联的都会被初始化加载。true falsefalseaggressiveLazyLoading当设置为‘true’的时候,懒加载的对象可能被任何懒属性全部加载。否则,每个属性都按需加载。true falsetrue

在SqlMapConfig.xml中配置:

    <settings>        <!-- 打开延迟加载的开关 -->        <setting name="lazyLoadingEnabled" value="true"/>        <!-- 将积极加载改为消极加载,即按需加载 -->        <setting name="aggressiveLazyLoading" value="false"/>    </settings>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

测试代码:

    @Test    public void findOrdersUserLazyLoading() throws Exception{        SqlSession sqlSession = sqlSessionFactory.openSession();        //创建代理对象        OrdersCustomMapper ordersMapperCustom = sqlSession.getMapper(OrdersCustomMapper.class);        //调用mapper的方法        List<Orders> list = ordersMapperCustom.findOrdersUserLazyLoading();        //遍历订单列表        for (Orders orders : list) {            //执行getUser()去查询用户信息,这里实现按需加载            User user = orders.getUser();            System.out.println(user);        }        sqlSession.close();    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

结果: 
这里写图片描述

延迟加载的思考: 
不使用mybatis提供的延迟加载功能是否可以实现延迟加载? 
实现方法: 
针对订单和用户两个表定义两个mapper方法。 
1、订单查询mapper方法 
2、根据用户id查询用户信息mapper方法 
默认使用订单查询mapper方法只查询订单信息。 
当需要关联查询用户信息时再调用根据用户id查询用户信息mapper方法查询用户信息。

延迟加载总结: 
作用: 
当需要查询关联信息时再去数据库查询,默认不去关联查询,提高数据库性能。 
只有使用resultMap支持延迟加载设置。 
场合: 
当只有部分记录需要关联查询其它信息时,此时可按需延迟加载,需要关联查询时再向数据库发出sql,以提高数据库性能。 
当全部需要关联查询信息时,此时不用延迟加载,直接将关联查询信息全部返回即可,可使用resultType或resultMap完成映射。

原创粉丝点击