(八)mybatis學習之高級映射(一對一、一對多、多對多)


一對一關聯查詢

resultType

resultType的對於關聯查詢是實時查詢的。

使用resultType來開發的話,就要將sql查詢出來的結果映射到某個pojo中。

resultType的開發比較簡單,就是查詢結果是什么,就去定義一個pojo類,添加對應的屬性名進行映射就OK。

resultMap

resultMap對於管理查詢,可以設置一些延遲加載的配置。

resultMap里配置一對一關聯,主要使用到association這個標簽,指定類型用javaType。

訂單pojo類:

public class OrderInfos {

private String id;
private String orderNo;//訂單號
private String mark;//留言(描述)
private String address;//地址(具體地址)
private String phone;//收貨人電話
private Integer quantity;//數量
private Double totalSum;//訂單總金額
private Date createTime;//訂單生成時間
private User user;

//....get set


用戶信息pojo類:

public class User {

private String id;
private String userName;//用戶名
private String nickName;//昵稱
private String password;//登錄密碼
private Integer sex;//性別
private Date birthday;//出生日期
private String province;//省
private String city;//市
private String county;//縣
private Date createTime;//創建時間

//... get set


配置文件內容:

<resultMap type="orderInfos" id="findOrderMap">
<!-- 映射訂單信息
id:指定查詢列中的唯一標識,如果有組合主鍵,則配置對個id
-->
<id column="id" property="id"/>
<result column="orderNo" property="orderNo"/>
<result column="mark" property="mark"/>
<result column="address" property="address"/>
<result column="createTime" property="createTime"/>
<!-- 訂單所對應的用戶信息 -->
<!-- association:用於映射關聯查詢單個對象的信息
property:要講關聯查詢的用戶信息映射到訂單pojo列中的哪個屬性里
javaType:表示關聯查詢的對象類型(可以使用別名)
-->
<association property="user" javaType="pojo.User">
<id column="user_id" property="id"/>
<result column="userName" property="userName"/>
<result column="sex" property="sex"/>
<result column="birthday" property="birthday"/>
<result column="password" property="password"/>
</association>
</resultMap>

<!-- 獲取訂單里的用戶信息 -->
<select id="findOrder" resultMap="findOrderMap">
select A.*,B.userName,B.sex,B.birthday,B.`password`
from tab_orderinfos as A
inner join tab_user as B on A.user_id=B.id
</select>

一對多關聯查詢

配置一對多關聯,需要在resultMap里使用collection標簽來實現,指定類型用ofType

訂單pojo類:

public class OrderInfos {

private String id;
private String orderNo;//訂單號
private String mark;//留言(描述)
private String address;//地址(具體地址)
private String phone;//收貨人電話
private Integer quantity;//數量
private Double totalSum;//訂單總金額
private Date createTime;//訂單生成時間

private List<OrderInfosDetail> detailList;

//... get set


訂單明細pojo類:

public class OrderInfosDetail {

private String id;
private String color;//顏色
private String size;//尺寸
private Double unitPrice;//價格
private Integer quantity;//數量
private Double totalSum;//總金額
//... get set


配置文件內容:

<resultMap type="orderInfos" id="oneToManyFindOrderMap">
<!-- 映射訂單信息
id:指定查詢列中的唯一標識,如果有組合主鍵,則配置對個id
-->
<id column="id" property="id"/>
<result column="orderNo" property="orderNo"/>
<result column="mark" property="mark"/>
<result column="address" property="address"/>
<result column="createTime" property="createTime"/>

<!-- 訂單所對應的用戶信息 -->
<!-- association:用於映射關聯查詢單個對象的信息
property:要講關聯查詢的用戶信息映射到訂單pojo列中的哪個屬性里
javaType:表示關聯查詢的對象類型(可以使用別名)
-->
<association property="user" javaType="pojo.User">
<id column="user_id" property="id"/>
<result column="userName" property="userName"/>
<result column="sex" property="sex"/>
<result column="birthday" property="birthday"/>
<result column="password" property="password"/>
</association>

<!-- 獲取訂單明細信息,一個訂單關聯查詢出多條明細,要使用collection來進行映射 -->
<!-- collection:對關聯查詢到的多條記錄進行映射
property:要講關聯查詢的明細信息映射到訂單pojo列中的哪個屬性里
ofType:指要映射到集合屬性中pojo的類型
-->
<collection property="detailList" ofType="orderInfosDetail">
<id column="detailId" property="id"/>
<result column="quantity" property="quantity"/>
<result column="color" property="color"/>
<result column="unitPrice" property="unitPrice"/>
</collection>
</resultMap>

<select id="oneToManyFindOrder" resultMap="oneToManyFindOrderMap">
select A.*,B.userName,B.sex,B.birthday,B.`password`,C.id detailId,C.quantity,C.color,C.unitPrice
from tab_orderinfos as A
inner join tab_user as B on A.user_id=B.id
left join tab_orderinfosdetail as C on A.id=C.orderInfos_id
</select>

這里我們發現訂單信息與用戶信息的配置,跟上面的一對一里的配置一樣。這種情況可以使用繼承,就不需要再進行配置了。

使用extends屬性設置了繼承以后,配置文件內容變為:

<resultMap type="orderInfos" id="oneToManyFindOrderMap" extends="findOrderMap">
<!-- 獲取訂單明細信息,一個訂單關聯查詢出多條明細,要使用collection來進行映射 -->
<!-- collection:對關聯查詢到的多條記錄進行映射
property:要講關聯查詢的明細信息映射到訂單pojo列中的哪個屬性里
ofType:指要映射到集合屬性中pojo的類型
-->
<collection property="detailList" ofType="orderInfosDetail">
<id column="detailId" property="id"/>
<result column="quantity" property="quantity"/>
<result column="color" property="color"/>
<result column="unitPrice" property="unitPrice"/>
</collection>
</resultMap>

<select id="oneToManyFindOrder" resultMap="oneToManyFindOrderMap">
select A.*,B.userName,B.sex,B.birthday,B.`password`,C.id detailId,C.quantity,C.color,C.unitPrice
from tab_orderinfos as A
inner join tab_user as B on A.user_id=B.id
left join tab_orderinfosdetail as C on A.id=C.orderInfos_id
</select>


多對多關聯查詢

多多對多的關聯查詢其實都是基於多對一,一對多的基礎上進行配置的。

會了一對一、一對多,多對多也就會了。這里不再多說。


延遲加載

什么是延遲加載?就是需要用到的時候再進行查詢,這就是延遲加載。 mybatis里association和collection都支持延遲加載。 這里就拿association來測試一下,collection用法一樣。 需要說明的是,延遲加載跟上面所說的一對一、一對多的查詢開發方式是不一樣的。上面的查詢都是實時的查詢出所有的數據,不是延遲加載。 針對上面所說的一對一,我們來實現一下它的延遲加載。 此時需要配置兩個sql配置: (1)查詢訂單信息 (2)根據訂單信息中的user_id,去查詢對應的用戶信息 最后的配置文件內容如下:
<resultMap type="orderInfos" id="lazyMap">
<!-- 映射訂單信息 -->
<id column="id" property="id"/>
<result column="orderNo" property="orderNo"/>
<result column="mark" property="mark"/>
<result column="address" property="address"/>
<result column="createTime" property="createTime"/>
<!-- 延遲加載訂單所對應的用戶信息
select:指定延遲加載需要執行的sql配置id
column:訂單信息中關聯查詢用戶信息的列(說白了,就是說訂單表中是根據那個列去查詢用戶信息的)
-->
<association property="user" javaType="pojo.User" select="lazyFindUserById" column="user_id"></association>
</resultMap>

<!-- 查詢訂單信息,用戶信息需要延遲加載,因為延遲加載是在association或collection中才能實現,所以這里需要使用resultMap來做映射 -->
<select id="findOrderAll" resultMap="lazyMap">
select * from tab_orderinfos
</select>

<!-- 根據id查詢用戶信息 -->
<select id="lazyFindUserById" parameterType="java.lang.String" resultType="user">
select * from tab_user where id=#{id}
</select>

注意:mybatis默認是不開啟延遲加載的。所以我們需要在sqlMapConfig.xml的settings里配置開啟延遲加載。具體的settings的信息請看文檔《3.1.2 settings》
在sqlMapConfig.xml配置settings開啟延遲加載:
<settings>
<!-- 開啟延遲加載
lazyLoadingEnabled:全局配置懶加載,如果設置為false,則所有關聯查詢都會被初始化加載。默認值是fasle。所以這里要設為true
aggressiveLazyLoading:當設置為true時,會對全部查詢發出sql了。所以我們應該要設置為false。為false時,需要用什么就查詢什么,按需加載。默認值是true
-->
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
</settings>

測試類:
@Test
public void test() throws Exception {
//獲取代理對象
OrderMapper orderMapper = (OrderMapper) context.getBean("orderMapper");


List<OrderInfos> list = orderMapper.findOrderAll();

for(OrderInfos order :list){
User user = order.getUser();
System.out.println(user.getUserName());
}

System.out.println(list);

}

}
結果:
2016-04-04 16:16:04,370 [main] DEBUG [mapper.OrderMapper.findOrderAll] - ==>  Preparing: select * from tab_orderinfos 
2016-04-04 16:16:04,418 [main] DEBUG [mapper.OrderMapper.findOrderAll] - ==> Parameters:
2016-04-04 16:16:04,980 [main] DEBUG [mapper.OrderMapper.findOrderAll] - <== Total: 22
2016-04-04 16:16:04,987 [main] DEBUG [org.mybatis.spring.SqlSessionUtils] - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4fb686]
2016-04-04 16:16:04,987 [main] DEBUG [org.springframework.jdbc.datasource.DataSourceUtils] - Returning JDBC Connection to DataSource
2016-04-04 16:16:18,278 [main] DEBUG [org.springframework.jdbc.datasource.DataSourceUtils] - Fetching JDBC Connection from DataSource
2016-04-04 16:16:18,279 [main] DEBUG [org.mybatis.spring.transaction.SpringManagedTransaction] - JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@104f568 [wrapping: com.mysql.jdbc.JDBC4Connection@1bd7522]] will not be managed by Spring
2016-04-04 16:16:18,281 [main] DEBUG [mapper.OrderMapper.lazyFindUserById] - ==> Preparing: select * from tab_user where id=?
2016-04-04 16:16:18,284 [main] DEBUG [mapper.OrderMapper.lazyFindUserById] - ==> Parameters: 2c9381ed460abc1101460abddf830000(String)
2016-04-04 16:16:18,302 [main] DEBUG [mapper.OrderMapper.lazyFindUserById] - <== Total: 1
2016-04-04 16:16:18,303 [main] DEBUG [org.springframework.jdbc.datasource.DataSourceUtils] - Returning JDBC Connection to DataSource
abc
2016-04-04 16:16:30,678 [main] DEBUG [org.springframework.jdbc.datasource.DataSourceUtils] - Fetching JDBC Connection from DataSource
2016-04-04 16:16:30,679 [main] DEBUG [org.mybatis.spring.transaction.SpringManagedTransaction] - JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@43690f [wrapping: com.mysql.jdbc.JDBC4Connection@1bd7522]] will not be managed by Spring
2016-04-04 16:16:30,681 [main] DEBUG [mapper.OrderMapper.lazyFindUserById] - ==> Preparing: select * from tab_user where id=?
2016-04-04 16:16:30,684 [main] DEBUG [mapper.OrderMapper.lazyFindUserById] - ==> Parameters: 2c9381ed460abc1101460abddf830000(String)
2016-04-04 16:16:30,702 [main] DEBUG [mapper.OrderMapper.lazyFindUserById] - <== Total: 1
2016-04-04 16:16:30,703 [main] DEBUG [org.springframework.jdbc.datasource.DataSourceUtils] - Returning JDBC Connection to DataSource
abc
2016-04-04 16:16:41,684 [main] DEBUG [org.springframework.jdbc.datasource.DataSourceUtils] - Fetching JDBC Connection from DataSource
2016-04-04 16:16:41,685 [main] DEBUG [org.mybatis.spring.transaction.SpringManagedTransaction] - JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@160e1bb [wrapping: com.mysql.jdbc.JDBC4Connection@1bd7522]] will not be managed by Spring
2016-04-04 16:16:41,685 [main] DEBUG [mapper.OrderMapper.lazyFindUserById] - ==> Preparing: select * from tab_user where id=?
2016-04-04 16:16:41,685 [main] DEBUG [mapper.OrderMapper.lazyFindUserById] - ==> Parameters: 2c9381ed460abc1101460abddf830000(String)
2016-04-04 16:16:41,689 [main] DEBUG [mapper.OrderMapper.lazyFindUserById] - <== Total: 1
2016-04-04 16:16:41,690 [main] DEBUG [org.springframework.jdbc.datasource.DataSourceUtils] - Returning JDBC Connection to DataSource
abc
2016-04-04 16:16:41,690 [main] DEBUG [org.springframework.jdbc.datasource.DataSourceUtils] - Fetching JDBC Connection from DataSource
2016-04-04 16:16:41,690 [main] DEBUG [org.mybatis.spring.transaction.SpringManagedTransaction] - JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@163eb77 [wrapping: com.mysql.jdbc.JDBC4Connection@1bd7522]] will not be managed by Spring
2016-04-04 16:16:41,690 [main] DEBUG [mapper.OrderMapper.lazyFindUserById] - ==> Preparing: select * from tab_user where id=?
2016-04-04 16:16:41,691 [main] DEBUG [mapper.OrderMapper.lazyFindUserById] - ==> Parameters: 2c9381ed460abc1101460abddf830000(String)
2016-04-04 16:16:41,695 [main] DEBUG [mapper.OrderMapper.lazyFindUserById] - <== Total: 1
2016-04-04 16:16:41,696 [main] DEBUG [org.springframework.jdbc.datasource.DataSourceUtils] - Returning JDBC Connection to DataSource
abc
2016-04-04 16:16:41,696 [main] DEBUG [org.springframework.jdbc.datasource.DataSourceUtils] - Fetching JDBC Connection from DataSource
2016-04-04 16:16:41,696 [main] DEBUG [org.mybatis.spring.transaction.SpringManagedTransaction] - JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@edd5f4 [wrapping: com.mysql.jdbc.JDBC4Connection@1bd7522]] will not be managed by Spring
2016-04-04 16:16:41,697 [main] DEBUG [mapper.OrderMapper.lazyFindUserById] - ==> Preparing: select * from tab_user where id=?
2016-04-04 16:16:41,698 [main] DEBUG [mapper.OrderMapper.lazyFindUserById] - ==> Parameters: 2c9381ed460abc1101460abddf830000(String)
2016-04-04 16:16:41,702 [main] DEBUG [mapper.OrderMapper.lazyFindUserById] - <== Total: 1
2016-04-04 16:16:41,702 [main] DEBUG [org.springframework.jdbc.datasource.DataSourceUtils] - Returning JDBC Connection to DataSource
abc
2016-04-04 16:16:41,702 [main] DEBUG [org.springframework.jdbc.datasource.DataSourceUtils] - Fetching JDBC Connection from DataSource
2016-04-04 16:16:41,702 [main] DEBUG [org.mybatis.spring.transaction.SpringManagedTransaction] - JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@b759cd [wrapping: com.mysql.jdbc.JDBC4Connection@1bd7522]] will not be managed by Spring
2016-04-04 16:16:41,702 [main] DEBUG [mapper.OrderMapper.lazyFindUserById] - ==> Preparing: select * from tab_user where id=?
2016-04-04 16:16:41,703 [main] DEBUG [mapper.OrderMapper.lazyFindUserById] - ==> Parameters: 2c9381ed460abc1101460abddf830000(String)
2016-04-04 16:16:41,705 [main] DEBUG [mapper.OrderMapper.lazyFindUserById] - <== Total: 1
2016-04-04 16:16:41,705 [main] DEBUG [org.springframework.jdbc.datasource.DataSourceUtils] - Returning JDBC Connection to DataSource
abc
2016-04-04 16:16:41,705 [main] DEBUG [org.springframework.jdbc.datasource.DataSourceUtils] - Fetching JDBC Connection from DataSource
2016-04-04 16:16:41,705 [main] DEBUG [org.mybatis.spring.transaction.SpringManagedTransaction] - JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@1497c25 [wrapping: com.mysql.jdbc.JDBC4Connection@175982a]] will not be managed by Spring
2016-04-04 16:16:41,705 [main] DEBUG [mapper.OrderMapper.lazyFindUserById] - ==> Preparing: select * from tab_user where id=?
2016-04-04 16:16:41,706 [main] DEBUG [mapper.OrderMapper.lazyFindUserById] - ==> Parameters: 2c9381ed460abc1101460abddf830000(String)
2016-04-04 16:16:41,727 [main] DEBUG [mapper.OrderMapper.lazyFindUserById] - <== Total: 1
2016-04-04 16:16:41,727 [main] DEBUG [org.springframework.jdbc.datasource.DataSourceUtils] - Returning JDBC Connection to DataSource
abc
2016-04-04 16:16:41,728 [main] DEBUG [org.springframework.jdbc.datasource.DataSourceUtils] - Fetching JDBC Connection from DataSource
2016-04-04 16:16:41,728 [main] DEBUG [org.mybatis.spring.transaction.SpringManagedTransaction] - JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@1825bfb [wrapping: com.mysql.jdbc.JDBC4Connection@175982a]] will not be managed by Spring
2016-04-04 16:16:41,728 [main] DEBUG [mapper.OrderMapper.lazyFindUserById] - ==> Preparing: select * from tab_user where id=?
2016-04-04 16:16:41,728 [main] DEBUG [mapper.OrderMapper.lazyFindUserById] - ==> Parameters: 2c9381ed460abc1101460abddf830000(String)
2016-04-04 16:16:41,731 [main] DEBUG [mapper.OrderMapper.lazyFindUserById] - <== Total: 1
2016-04-04 16:16:41,731 [main] DEBUG [org.springframework.jdbc.datasource.DataSourceUtils] - Returning JDBC Connection to DataSource
abc

通過上面的日志打印,可以很清楚的看到,在for循環遍歷訂單信息時,當我們使用getUser()時,才發出sql,查詢數據獲取結果。這樣就實現了延遲加載。









注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com