1. 程式人生 > >mybatis——關聯查詢

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='[email protected]', id=1, userId=1, num=1}
OrdersExt{username='修改', email='[email protected]', 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='[email protected]', phone='null', address='null'}, id=0, userId=0, num=0}
OrdersExt{, user=User{id=1, username='修改', password='null', email='[email protected]', 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='[email protected]', phone='121212', address='', ordersList=[[email protected]]}
User{id=9, username='bbb', password='null', email='[email protected]', phone='bbb', address='bbb', ordersList=[[email protected]]}
User{id=12, username='小小', password='null', email='[email protected]', phone='123', address='sasas', ordersList=[[email protected]]}
User{id=17, username='小', password='null', email='[email protected]', phone='123', address='sasas', ordersList=[[email protected]]}
User{id=20, username='小xiao小', password='null', email='[email protected]', phone='123', address='sasas', ordersList=[[email protected]]}

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>