<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 156,  comments - 601,  trackbacks - 0

        好久的筆記了,趁剛好休息整理文檔,翻出這一部分,稍加整理后,就發(fā)上來給大家共享一下,希望對各位有所幫助。

        關(guān)于LazyLoadException異常,使用過Hibernate O/R Mapping工具的人應(yīng)該都遇到過,網(wǎng)上也是有很多解決的方案,其中Spring提供的一個方案就是在web.xml增加一個filter,示例代碼如下:

    <filter>  
        
    <filter-name>entityManager</filter-name>  
        
    <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>  
    </filter>  
      
    <filter-mapping>  
        
    <filter-name>entityManagerFilter</filter-name>  
        
    <url-pattern>*.action</url-pattern>  
    </filter-mapping> 

      解決辦法有了,接下來應(yīng)該會有人好奇:這個配置filter后它是如何工作的?
      下面來分析一下這個功能實(shí)現(xiàn)的源代碼, 不過之前,比較重要的是了解,為何會出現(xiàn)lazyload exception的異常發(fā)生。

       下面我模擬寫了一段代碼,這段代碼就會發(fā)生該異常
       注:只是為了說明,相關(guān)的代碼就省略了。

    @Entity
    public class Room {

     @Id
     @Column(length
    =32)
     
    private String id;

     @Column(length
    =20)
     
    private code;
     
     @OneToMany(mappedBy
    ="room"//default is use lazy load strategy 
     private Set desks;
    }

    @Entity
    public class Desk {

         @Id
         @Column(length
    =32)
         
    private String id;
        
         @Column(length
    =20)
         
    private code;
         
         @ManyToOne
         
    private Room root;

    }

    public class RoomSerivce {

        @Transactional(readOnly
    =true)
        
    public Room getRoomById(String roomId) {
          Assert.notBlank(roomId, 
    "room'id is null);
            return getDao().findById(roomId);
        
        }

    }


     1 public class RoomServiceTest {
     2 
     3     public static void main(String[] args[]) {
     4     
     5         //get service from spring beanfactory
     6         RoomService service = SpringContext.getSerivce("roomService");
     7         Assert.notNull(service, " roomService bean not exsit");
     8     
     9       Room room = service.getRoomById("1");
    10       //here lazy exception throw out
    11       Set Desks = room.getDesks();
    12       CollectionsUtils.toString(Desks);
    13     }
    14 }

       分析這段代碼,我們不難發(fā)現(xiàn),在RoomServiceTest這個測試的例子中,因?yàn)槭褂昧嘶贏nnotation的聲明性事務(wù),所以在RoomSerivce.getRoomById方法運(yùn)行結(jié)束后,事務(wù)就已經(jīng)提交了。但示例中Room實(shí)體與Desk實(shí)例的關(guān)系使用的是lazy fetch的策略,此時Room對象中的desks集合還是為空。
    當(dāng)執(zhí)行到下面兩句時(這才真正使用到desks集合時)
      Set Desks = room.getDesks();
      CollectionsUtils.toString(Desks);
    Hibernate就會根據(jù)原來lazy設(shè)定的方式,取EntityManager, 根據(jù)它從數(shù)據(jù)庫查詢 Desk實(shí)現(xiàn)的數(shù)據(jù),這時上面我們已經(jīng)提到,事務(wù)已經(jīng)隨getRoomById方法的運(yùn)行結(jié)束提交. EntityManager對象也已經(jīng)關(guān)閉。此時再調(diào)用 EntityManager操作,就會報EntityManager has been closed 異常(lazy load exception)

       ok, 清楚這塊,大家有時可能也猜想到了Spring這個解決方案是怎么處理的了。
       Spring的TransactionInterceptor 其就是通過AOP負(fù)責(zé)攔截著所有針對事務(wù)TransactionManager的操作.
       這樣Spring就可以針對lazy異常進(jìn)行攔截了。

       清楚上面的后,下面的代碼是非常好理解了,來看一下OpenEntityManagerInViewFilter的代碼:
    我加了些注釋,大家很容易明白:

     1     protected void doFilterInternal(
     2             HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
     3             throws ServletException, IOException {
     4 
     5       //通過WebApplicationContext,從Web服務(wù)中取得context實(shí)例后,根據(jù)EntityManagerFactory.class類型
     6       //取得EntityManagerFacotry實(shí)例
     7         EntityManagerFactory emf = lookupEntityManagerFactory(request);
     8         boolean participate = false;
     9 
    10         //如果靜態(tài)方法hasResource已經(jīng)有EntityManagerFactory實(shí)例了,就不用再通過
    11         //EntityManagerFactory創(chuàng)建一個新EntityManger了
    12         if (TransactionSynchronizationManager.hasResource(emf)) {
    13             // Do not modify the EntityManager: just set the participate flag.
    14             participate = true;
    15         }
    16         else {
    17             logger.debug("Opening JPA EntityManager in OpenEntityManagerInViewFilter");
    18             try {
    19             //通過EntityManagerFactory創(chuàng)建一個新EntityManger,并通過bindResource方法
    20             //保存到TransactionSynchronizationManager中
    21             //這樣,通TransactionSynchronizationManager的getResource方法取得EntityMangerHolder
    22                 EntityManager em = createEntityManager(emf);
    23                 TransactionSynchronizationManager.bindResource(emf, new EntityManagerHolder(em));
    24             }
    25             catch (PersistenceException ex) {
    26                 throw new DataAccessResourceFailureException("Could not create JPA EntityManager", ex);
    27             }
    28         }
    29 
    30         try {
    31             filterChain.doFilter(request, response);
    32         }
    33 
    34         finally {
    35             if (!participate) {
    36             //每次請求結(jié)束后,就把EntityManager關(guān)閉
    37                 EntityManagerHolder emHolder = (EntityManagerHolder)
    38                         TransactionSynchronizationManager.unbindResource(emf);
    39                 logger.debug("Closing JPA EntityManager in OpenEntityManagerInViewFilter");
    40                 EntityManagerFactoryUtils.closeEntityManager(emHolder.getEntityManager());
    41             }
    42         }
    43     }
    44    

        上面的代碼就不用多解釋了, 到現(xiàn)在已經(jīng)很清楚知道Spring針對 Hibernate的Lazy問題是怎么解決的。
        當(dāng)然我們可以擴(kuò)展到除Web服務(wù)以外,來實(shí)現(xiàn)解決lazy的問題。(我們自己來管理TransactionSynchronizationManager就可以了)
       
        當(dāng)然Spring針對 Hibernate(非JPA的實(shí)現(xiàn))原理也是一樣,只是它針對的SessionFactory,也是由TransactionSynchronizationManager來統(tǒng)一管理。
       
        最后如果大家如還有不清楚的,歡迎一起討論。
       
    Good Luck!
    Yours Matthew!

    posted on 2008-10-11 18:01 x.matthew 閱讀(3106) 評論(3)  編輯  收藏 所屬分類: Spring|Hibernate|Other framework
    主站蜘蛛池模板: 青青草国产免费国产是公开| 国产成人久久精品亚洲小说| 动漫黄网站免费永久在线观看| 亚洲一本到无码av中文字幕| www.亚洲色图| 一级特黄aa毛片免费观看| 亚洲不卡视频在线观看| 亚洲精品无码久久久| 美丽的姑娘免费观看在线播放 | 啊v在线免费观看| 日本免费一区尤物| 99在线热播精品免费99热| 亚洲精品国产福利片| 亚洲AⅤ视频一区二区三区| 18女人毛片水真多免费| 无码免费又爽又高潮喷水的视频| 亚洲国产成人片在线观看无码 | 国产女高清在线看免费观看| 成全视频免费观看在线看| 亚洲AV无码国产剧情| 亚洲嫩草影院久久精品| 亚洲成人国产精品| 国产乱子精品免费视观看片| 国产黄片不卡免费| 亚洲爆乳AAA无码专区| 亚洲电影在线播放| 亚洲热线99精品视频| 免费看国产一级片| 久久天天躁狠狠躁夜夜免费观看| 99免费在线视频| 精品特级一级毛片免费观看| 亚洲一区二区三区免费在线观看| 亚洲中文久久精品无码| 四虎影视精品永久免费网站| 在线观看av永久免费| 最近中文字幕免费2019| 免费精品99久久国产综合精品| 日本高清不卡中文字幕免费| 亚洲欧美日韩中文无线码 | 97视频免费观看2区| WWW免费视频在线观看播放|