mybatis——关联查询

1 需求场景

订单表:orders
用户表:users
从查询订单信息出发,关联查询用户信息为一对一查询。如果从用户信息出发,查询用户下的订单信息则为一对多查询,因为一个用户可以下多个订单。

2 one to one

查询所有订单信息,关联查询下单用户信息。

2.1 resultType

2.1.1 分析

1、如果使用resultType进行结果映射,则查询的列名和映射pojo的属性名称要一致。
2、关联查询的结果集,既包含订单信息,又包含用户信息。使用订单po或者用户po类都无法完成结果映射。
3、需要定义扩展po类,此类继承订单信息po类,同时还要包括用户信息:

2.1.2 定义扩展的pojo类

public class OrdersExt extends Orders {
    String username;
    String email;
}

2.1.3 OrderMapp.xml

<select id="findOrderAndUser" resultType="OrdersExt">
        SELECT orders.*,user.username,user.email
        FROM orders ,USER
        WHERE orders.userid = user.id
    </select>

2.1.4 OrderMapper.java

public interface OrdersMapper {
    List<OrdersExt> findOrderAndUser();
}

2.1.5 测试

@Test
    public void TestFindOrderAndUser(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        OrdersMapper ordersMapper = sqlSession.getMapper(OrdersMapper.class);
        List<OrdersExt> orders= ordersMapper.findOrderAndUser();
        for (OrdersExt oe:orders)
            System.out.println(oe);
    }

输出

OrdersExt{username='修改', email='test@', id=1, userId=1, num=1}
OrdersExt{username='修改', email='test@', id=2, userId=1, num=1}

2.2 ResultMap

使用resultMap进行结果映射,定义专门的resultMap用于映射一对一查询结果。

2.2.1 OrderExt

public class OrdersExt extends Orders {
//    String username;
//    String email;
    User user;

2.2.2 OrderMapper.xml

<resultMap id="orderAndUserMap" type="OrdersExt">
		<!-- 
		id标签:映射查询结果的唯一列(主键列)
			column:查询sql的列名
			property:映射结果的属性名
		-->
       <id column="id" property="id"></id>
        <result column="userId" property="userId"/>
        <result column="num" property="num"/>
        <association property="user" javaType="pojo.User">
            <id column="userId" property="id"/>
            <result column="username" property="username" />
            <result column="email" property="email" />
        </association>
    </resultMap>
    <select id="findOrdersAndUserMap" resultMap="orderAndUserMap" >
        SELECT O.* ,u.username,u.email
        FROM Orders o JOIN USER u ON u.id = o.userId
    </select>

association:表示进行一对一关联查询映射
property:表示关联查询的结果存储在orderExt的user属性中
javaType:表示关联查询的映射结果类型

2.2.3 OrderMapper.java

public interface OrdersMapper {
    List<OrdersExt> findOrdersAndUserMap();
    List<OrdersExt> findOrderAndUser();
}

2.2.4 测试

@Test
    public void TestFindOrderAndUserMap(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        OrdersMapper ordersMapper = sqlSession.getMapper(OrdersMapper.class);
        List<OrdersExt> orders= ordersMapper.findOrdersAndUserMap();
        for (OrdersExt oe:orders)
            System.out.println(oe);
    }

输出

OrdersExt{, user=User{id=1, username='修改', password='null', email='test@', phone='null', address='null'}, id=0, userId=0, num=0}
OrdersExt{, user=User{id=1, username='修改', password='null', email='test@', phone='null', address='null'}, id=0, userId=0, num=0}

3 one to many

根据user查询order信息,一对多查询,只能使用resultMap

3.1 修改User

public class User {
    int id;
    String username;
    String password;
    String email;
    String phone;
    String address;
    List<Orders> ordersList;
}

3.2 UserMapper.xml

<resultMap id="userAndOrders" type="user">
        <id property="id" column="id"/>
        <result property="username" column="username"/>
        <result property="email" column="email" />
        <result property="phone" column="phone"/>
        <result property="address" column="address"/>
        <!-- 一对多关系映射 -->
        <collection property="ordersList" ofType="orders">
            <id property="id" column="id"/>
            <result property="userId" column="id"/>
            <result property="num" column="num" />
        </collection>
    </resultMap>

    <select id="getUserAndOrders" resultMap="userAndOrders">
        SELECT u.*,o.id,o.num
        FROM user u LEFT JOIN orders o ON u.id = o.userId
    </select>

Collection标签:定义了一对多关联的结果映射。
property=“ordersList”:关联查询的结果集存储在User对象的上哪个属性。
ofType=“orders”:指定关联查询的结果集中的对象类型即List中的对象类型。

3.3 UserMapper.java

public interface UserMapper {
    User findUserById(Integer id);
    void addUser(User user);
    List<User> getUserByName(String username);
    List<User> getUserAndOrders();
}

3.4 测试

    @Test
    public void testGetUserAndOrders(){
        SqlSession sqlSession  = null;
        try {
            sqlSession = sqlSessionFactory.openSession();
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            List<User> userList = userMapper.getUserAndOrders();
            for (User u:userList)
                System.out.println(u);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (sqlSession!=null)
                sqlSession.close();
        }
    }
}

输出

User{id=1, username='修改', password='null', email='test@', phone='121212', address='', ordersList=[pojo.Orders@4eb7f003]}
User{id=9, username='bbb', password='null', email='[email protected]', phone='bbb', address='bbb', ordersList=[pojo.Orders@eafc191]}
User{id=12, username='小小', password='null', email='1@com', phone='123', address='sasas', ordersList=[pojo.Orders@612fc6eb]}
User{id=17, username='小', password='null', email='1@com', phone='123', address='sasas', ordersList=[pojo.Orders@1060b431]}
User{id=20, username='小xiao小', password='null', email='1@com', phone='123', address='sasas', ordersList=[pojo.Orders@612679d6]}

4 延迟加载

延迟加载,也称为懒加载,是指在进行关联查询时,按照设置延迟规则推迟对关联对象的select查询。延迟加载可以有效的减少数据库压力。
Mybatis的延迟加载,需要通过resultMap标签中的association和collection子标签才能演示成功。
注意:MyBatis的延迟加载只是对关联对象的查询有延迟设置,对于主加载对象都是直接执行查询语句的。

4.1 分类

 直接加载: 执行完对主加载对象的select语句,马上执行对关联对象的select查询。
 侵入式延迟:执行对主加载对象的查询时,不会执行对关联对象的查询。但当要访问主加载对象的详情时,就会马上执行关联对象的select查询。即对关联对象的查询执行,侵入到了主加载对象的详情访问中。也可以这样理解:将关联对象的详情侵入到了主加载对象的详情中,即将关联对象的详情作为主加载对象的详情的一部分出现了。
 深度延迟:执行对主加载对象的查询时,不会执行对关联对象的查询。访问主加载对象的详情时也不会执行关联对象的select查询。只有当真正访问关联对象的详情时,才会执行对关联对象的select查询。

4.2 直接加载

lazyLoadingEnabled进行设置,默认就是false。

<settings>
    <!-- 延迟加载总开关 -->
    <setting name="lazyLoadingEnabled" value="false"/>
</settings>

在这里插入图片描述

4.3 侵入式延迟

<settings>
    <!-- 延迟加载总开关 -->
    <setting name="lazyLoadingEnabled" value="true"/>
    <!-- 侵入式延迟加载开关 -->
    <setting name="aggressiveLazyLoading" value="true"/>
</settings>

4.4 深度延迟加载

<settings>
    <!-- 延迟加载总开关 -->
    <setting name="lazyLoadingEnabled" value="true"/>
    <!-- 侵入式延迟加载开关 -->
    <setting name="aggressiveLazyLoading" value="false"/>
</settings>

猜你喜欢

转载自blog.csdn.net/ccoran/article/details/85045517