欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Mybatis如何實現(xiàn)關(guān)聯(lián)屬性懶加載

 更新時間:2021年07月14日 09:59:51   作者:code_mo  
這篇文章主要介紹了Mybatis如何實現(xiàn)關(guān)聯(lián)屬性懶加載的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

Mybatis 關(guān)聯(lián)屬性懶加載

延遲加載配置

mybatis默認沒有開啟延遲加載,需要在config.xml中setting配置。

lazyLoadingEnabled:true使用延遲加載,false禁用延遲加載,默認為false。

aggressiveLazyLoading:true啟用時,當(dāng)延遲加載開啟時訪問對象中一個懶對象屬性時,將完全加載這個對象的所有懶對象屬性。false,當(dāng)延遲加載時,按需加載對象屬性(即訪問對象中一個對象屬性時,不會加載對象中的引用屬性)。默認為true。

修改延遲加載需要的select語句

延遲加載場景分析

查詢訂單時,需要關(guān)聯(lián)查詢訂單明細表

假設(shè)有10 個訂單,每個訂單有5個明細信息。

如果用戶僅僅需要查看訂單信息,不需要訂單明細信息,但是查詢了10+50個對象到內(nèi)存(只有10個是用戶想要的)。顯然是增加內(nèi)存的負擔(dān)。

如果用戶的需求僅僅是查詢訂單信息,我僅僅訂單信息用戶,沒有查詢訂單的詳情,那么,內(nèi)存中只有10對象(10個對象全是客戶想的),這樣做顯然 節(jié)省了內(nèi)存。

業(yè)務(wù)需求特點:需要的時候在進行查詢,不需要的時候不盡興查詢,這種情況就是延遲加載,也叫作懶加載。

配置過程

去掉sql語句中對user表的查詢語句

對resultMap orderAndUser 進行修改

注意:查詢訂單時要同時查詢userid,避免查詢user時沒有憑據(jù)

修改orderMapper.xml文件select語句

<!-- 關(guān)聯(lián)屬性延遲加載 -->
	<select id="queryOrderAndUser" resultMap="orderAndUser">
		select
		o.id oids,o.orderid,o.createtime,o.note,o.userid
		from orders o,t_user u
		where o.userid=u.id
	</select>
	<resultMap type="orders" id="orderAndUser">
		<id property="id" column="oids"></id>
		<result property="orderId" column="orderid"></result>
		<result property="createtime" column="createtime" />
		<result property="note" column="note" />
		<association property="user" javaType="users" 
		select="net.neuedu.mybatis.mapper.UserMapper.queryUserById" column="userid">
			<!-- 
				這里不查詢用戶的信息,而是將用的信息放在另外一個查詢中
				column是order表中的userid字段
			 -->
		</association>
	</resultMap>

因為在assocication多了一個select元素,就要在UserMapper中多加一個方法。

 //根據(jù)ID查詢用戶
 public Users queryUserById(Integer id);

在UserMapper.xml中添加queryUserById的select

 <!-- public Users queryUserById(Integer id); -->
 <select id="queryUserById" parameterType="int" resultType="users">
  select * from t_user where id=#{id}
 </select>

Mybatis注解方式懶加載失效分析

本人在使用spring mvc + mybatis的后臺結(jié)構(gòu)的項目的時候,在使用mybatis的懶加載出現(xiàn)了一些問題:

明明懶加載的配置都正確了,但就是用debug斷點調(diào)試的時候懶加載的屬性總是提前加載,在經(jīng)過幾天的不斷努力之后,終于發(fā)現(xiàn)了原因:

mybatis懶加載配置:

<!-- 查詢時,關(guān)閉關(guān)聯(lián)對象即時加載以提高性能 -->
<setting name="lazyLoadingEnabled" value="true" />
<!-- 設(shè)置關(guān)聯(lián)對象加載的形態(tài),此處為按需加載字段(加載字段由SQL指 定),不會加載關(guān)聯(lián)表的所有字段,以提高性能 -->
<setting name="aggressiveLazyLoading" value="false" />

懶加載查詢語句:

@Select("select * from user_main where username=#{username}")
 @Results({
       @Result(property = "roleNames", column = "id", many = @Many(fetchType=FetchType.LAZY,select = "getRoleNamesByUserId")),
       @Result(property = "permissionNames", column = "id", many = @Many(fetchType=FetchType.LAZY,select = "getPermissionsByUserId"))
   })
public UserPO getUserByUsername(@Param("username")String username);

測試用例:

 @Test
   public void testGetUserByUsername() throws Exception {
     SqlSession session = sqlSessionFactory.openSession();
     try {
       UserMapper userMapper = session.getMapper(UserMapper.class);
       UserPO userPo = userMapper.getUserByUsername("zhangsan");
       System.out.println(userPo);
       System.out.println(userPo.getPermissionNames());
//       List<String> map = userMapper.getRoleMain();
//       System.out.println(map);
       session.close();
     } finally {
       session.close();
     }
   }

結(jié)果調(diào)試測試用例的時候,使用debug卻發(fā)現(xiàn)懶加載并沒有生效,后來看了mybatis懶加載的源碼,依然沒有發(fā)現(xiàn)原因,感覺就是roleNames和permissionNames就是突然的加載了,斷點也捕捉不到,也沒有博捉到觸發(fā)的事件,這時樓主我就很奇怪了,最后經(jīng)過幾天的努力終于發(fā)現(xiàn)了原因:

mybatis源碼:configuration

protected Set<String> lazyLoadTriggerMethods = new HashSet<String>(Arrays.asList(new String[] { "equals", "clone", "hashCode", "toString" }));

默認這四個方法或觸發(fā)懶加載,當(dāng)然,觸發(fā)懶加載的方法還有g(shù)etRoleNames 和 getPermissions ,這兩個(只針對當(dāng)前實例)

然后通過sysout輸出的時候,發(fā)現(xiàn)hashcode和equals方法被莫名的觸發(fā)了,而且debug斷點還捕捉不到,然后roleNames和permissionNames就被莫名的加載了

最后發(fā)現(xiàn),這個問題和debug的原理有一定的關(guān)系,

原來,在顯示debug的黃色框框時,debug會另起一個線程,然后重新調(diào)用一遍代碼,然后顯示userpo信息的時候,又會調(diào)用userpo的hashcode方法和tostring方法,

這樣的話,就會導(dǎo)致這兩個方法會在debug線程內(nèi)觸發(fā)懶加載,造成的效果就是懶加載失效,但是實際上懶加載是生效了的,只是在debug模式上被觸發(fā)了,而且用斷點還捕捉不到,就會形成一個奇怪的問題,如果想用debug來查看效果,也是很簡單:

通過將觸發(fā)默認的四個方法屏蔽來查看效果,但是不支持,因為這樣的話,可能會影響實體的hash排序等問題,即使是用了這個方法,也是建議看完效果以后改成默認的

這種事代碼方式的,還有一種是配置文件方式的(自己從網(wǎng)上找)

configuration.setLazyLoadTriggerMethods(new HashSet<String>());

還有一種更好的方式來查看懶加載的效果,那就是mybatis的默認日志,建議將日志級別調(diào)成debug(這個debug級別和debug模式不一樣),然后執(zhí)行的時候就可以通過sql語句的打印來判斷懶加載是否生效。

其實這個問題的分析最后,還是在說debug斷點調(diào)試的問題,它的這種原理需要注意,特別是會在另一個線程調(diào)用hashcode和tostring方法,相信在很多方面會影響到我們,希望大家能夠注意吧~

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • struts2實現(xiàn)簡單文件下載功能

    struts2實現(xiàn)簡單文件下載功能

    這篇文章主要為大家詳細介紹了struts2實現(xiàn)簡單文件下載功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • Java中FileOutputStream類的使用

    Java中FileOutputStream類的使用

    java.io.FileOutputStream類是文件輸出流,用于將數(shù)據(jù)寫出到文件,下面就來介紹一下Java中FileOutputStream類的使用,具有一定的參考價值,感興趣的可以了解一下
    2023-10-10
  • java實現(xiàn)字符串的全排列

    java實現(xiàn)字符串的全排列

    這篇文章主要為大家詳細介紹了java實現(xiàn)字符串的全排列,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-02-02
  • 淺談HashMap中7種遍歷方式的性能分析

    淺談HashMap中7種遍歷方式的性能分析

    本文先從HashMap的遍歷方法講起,然后再從性能、原理以及安全性等方面,來分析HashMap各種遍歷方式的優(yōu)勢與不足
    2021-06-06
  • 詳解Java關(guān)鍵字final

    詳解Java關(guān)鍵字final

    今天帶大家學(xué)習(xí)Java基礎(chǔ)知識,文中對關(guān)鍵字final作了非常詳細的介紹,對正在學(xué)習(xí)Java的小伙伴們很有幫助,需要的朋友可以參考下
    2021-05-05
  • Java線程(Thread)四種停止方式代碼實例

    Java線程(Thread)四種停止方式代碼實例

    這篇文章主要介紹了Java線程(Thread)四種停止方式代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-03-03
  • java?map的key值轉(zhuǎn)駝峰命名的方法

    java?map的key值轉(zhuǎn)駝峰命名的方法

    這篇文章主要介紹了java?map的key值轉(zhuǎn)駝峰,通過實例代碼介紹了Map把“_”形式的key轉(zhuǎn)化為駝峰形式,本文通過實例代碼給大家介紹的非常詳細,需要的朋友可以參考下
    2023-12-12
  • 詳解Spring Cloud Hystrix斷路器實現(xiàn)容錯和降級

    詳解Spring Cloud Hystrix斷路器實現(xiàn)容錯和降級

    本篇文章主要介紹了詳解Spring Cloud Hystrix斷路器實現(xiàn)容錯和降級,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-05-05
  • 使用Spring開啟注解AOP的支持放置的位置

    使用Spring開啟注解AOP的支持放置的位置

    這篇文章主要介紹了使用Spring開啟注解AOP的支持放置的位置,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Java 垃圾回收機制詳解(動力節(jié)點Java學(xué)院整理)

    Java 垃圾回收機制詳解(動力節(jié)點Java學(xué)院整理)

    在系統(tǒng)運行過程中,會產(chǎn)生一些無用的對象,這些對象占據(jù)著一定的內(nèi)存,如果不對這些對象清理回收無用對象的內(nèi)存,可能會導(dǎo)致內(nèi)存的耗盡,所以垃圾回收機制回收的是內(nèi)存。下面通過本文給大家詳細介紹java垃圾回收機制,一起學(xué)習(xí)吧
    2017-02-02

最新評論