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>