badqiu

          XPer
          隨筆 - 46, 文章 - 3, 評論 - 195, 引用 - 0
          數(shù)據(jù)加載中……

          使用動態(tài)代理解決Hibernate序列化,避免延遲加載問題.

          在使用Ajax: Hibernate Entity => json,?Flex RemoteObject:?Hibernate Entity => ActionScript Object的過程,經常碰到如下問題:

          問題:

          1.Hibernate碰到延遲加載的屬性訪問時如果session被關閉則拋出LazyInitializationException

          2.Hibernate中的one-to-many等關聯(lián)關系在序列化時如果沒有控制,則將整個數(shù)據(jù)庫都有可能被全部序列化

          3.過多的使用DTO/ValueObject解決這個問題.

          解決辦法:

          對Entity對象生成一個動態(tài)代理,攔截getXXXX()方法,如果訪問的是延遲加載的屬性,則return null,而不拋出LazyInitializationException,遞歸生成屬性的代理,只要碰到未延遲加載的屬性,而序列化會自動停止.避免將整個Entity序列化傳播,導致可能序列化整個數(shù)據(jù)庫的問題.

          類似解決方案:

          dwr中HibernateConverter,在序列化時如上類似,碰到延遲加載的屬性自動停止convert工作.而HibernateBeanSerializer則一勞永逸,無論object => json都可以工作.

          ?

          使用用例:

          ?

          Java代碼 復制代碼
          1. //role為原始對象 ??
          2. role?=?(Role)roleDao.getById( new ?Long( 1 )); ??
          3. //生成的動態(tài)代理proxyRole,訪問延遲加載的屬性將return?null ??
          4. Role?proxyRole?=?(Role) new ?HibernateBeanSerializer<Role>(role).getProxy(); ??
          5. assertNotNull(role.getResource());?? ??
          6. assertNull(proxyRole.getResource());? //延遲加載,為null ??
          7. ??
          8. Hibernate.initialize(role.getResource());? //抓取進來 ??
          9. assertNotNull(proxyRole.getResource());? //不為null ??

          ??

          ?

          源碼.

          Java代碼 復制代碼
          1. package ?cn.org.rapid_framework.util; ??
          2. ??
          3. import ?java.lang.reflect.Modifier; ??
          4. import ?java.util.ArrayList; ??
          5. import ?java.util.Collection; ??
          6. import ?java.util.LinkedHashMap; ??
          7. import ?java.util.LinkedHashSet; ??
          8. import ?java.util.List; ??
          9. import ?java.util.Map; ??
          10. import ?java.util.Set; ??
          11. ??
          12. import ?org.aopalliance.intercept.MethodInterceptor; ??
          13. import ?org.aopalliance.intercept.MethodInvocation; ??
          14. import ?org.hibernate.Hibernate; ??
          15. import ?org.hibernate.collection.PersistentCollection; ??
          16. import ?org.hibernate.proxy.HibernateProxy; ??
          17. import ?org.springframework.aop.framework.ProxyFactory; ??
          18. import ?org.springframework.util.StringUtils; ??
          19. ??
          20. /** ?
          21. ?*?用于Hibernate?Object?的序列化,訪問延遲加載的屬性不會拋出LazyInitializationException,而會返回null值. ?
          22. ?*?使用: ?
          23. ?*?<pre> ?
          24. ?*?Blog?proxyBlog?=?new?HibernateBeanSerializer(blog).getProxy(); ?
          25. ?*?</pre> ?
          26. ?*?@author?badqiu ?
          27. ?*?@param?<T> ?
          28. ?*/ ??
          29. public ? class ?HibernateBeanSerializer?<T>?{ ??
          30. ????T?proxy?=? null ; ??
          31. ???? /** ?
          32. ?????*/ ??
          33. ???? public ?HibernateBeanSerializer(T?object,String...?excludesProperties)?{ ??
          34. ???????? if (object?==? null )?{ ??
          35. ???????????? this .proxy?=? null ; ??
          36. ????????} else ?{ ??
          37. ????????????ProxyFactory?pf?=? new ?ProxyFactory(); ??
          38. ????????????pf.setTargetClass(object.getClass()); ??
          39. ????????????pf.setOptimize( true ); ??
          40. ????????????pf.setTarget(object); ??
          41. ????????????pf.setProxyTargetClass( true ); ??
          42. ????????????pf.setOpaque( true ); ??
          43. ????????????pf.setExposeProxy( true ); ??
          44. ????????????pf.setPreFiltered( true ); ??
          45. ????????????HibernateBeanSerializerAdvice?beanSerializerAdvice?=? new ?HibernateBeanSerializerAdvice(); ??
          46. ????????????beanSerializerAdvice.setExcludesProperties(excludesProperties); ??
          47. ????????????pf.addAdvice(beanSerializerAdvice); ??
          48. ???????????? ??
          49. ???????????? this .proxy?=?(T)pf.getProxy(); ??
          50. ????????} ??
          51. ????} ??
          52. ??
          53. ???? public ?T?getProxy(){ ??
          54. ???????? return ? this .proxy; ??
          55. ????} ??
          56. ???? ??
          57. ???? static ? private ? class ?HibernateBeanSerializerAdvice? implements ?MethodInterceptor?{ ??
          58. ???????? private ?String[]?excludesProperties?=? new ?String[ 0 ];? ??
          59. ???????? public ?String[]?getExcludesProperties()?{ ??
          60. ???????????? return ?excludesProperties; ??
          61. ????????} ??
          62. ???????? public ? void ?setExcludesProperties(String[]?excludesProperties)?{ ??
          63. ???????????? this .excludesProperties?=?excludesProperties?==? null ??? new ?String[ 0 ]?:?excludesProperties; ??
          64. ????????} ??
          65. ???????? public ?Object?invoke(MethodInvocation?mi)? throws ?Throwable?{ ??
          66. ????????????String?propertyName?=?getPropertyName(mi.getMethod().getName()); ??
          67. ????????????Class?returnType?=?mi.getMethod().getReturnType(); ??
          68. ???????????? ??
          69. ???????????? if (propertyName?==? null )?{ ??
          70. ???????????????? return ?mi.proceed(); ??
          71. ????????????} ??
          72. ???????????? if (!Hibernate.isPropertyInitialized(mi.getThis(),?propertyName))?{ ??
          73. ???????????????? return ? null ; ??
          74. ????????????} ??
          75. ???????????? if (isExclude(mi,?propertyName))?{ ??
          76. ???????????????? return ? null ; ??
          77. ????????????} ??
          78. ???????????? ??
          79. ????????????Object?returnValue?=?mi.proceed(); ??
          80. ???????????? return ?processReturnValue(returnType,?returnValue); ??
          81. ????????} ??
          82. ???????? ??
          83. ???????? private ?Object?processReturnValue(Class?returnType,?Object?returnValue)?{ ??
          84. ???????????? if (returnValue?==? null ) ??
          85. ???????????????? return ? null ; ??
          86. ???????????? if (returnType?!=? null ?&&?Modifier.isFinal(returnType.getModifiers()))?{ ??
          87. ???????????????? return ?returnValue; ??
          88. ????????????} ??
          89. ???????????? //This?might?be?a?lazy-collection?so?we?need?to?double?check ??
          90. ???????????? if (!Hibernate.isInitialized(returnValue))?{ ??
          91. ???????????????? return ? null ;???????????????? ??
          92. ????????????} ??
          93. ???????????? ??
          94. ???????????? //this?is?Hibernate?Object ??
          95. ???????????? if (returnValue? instanceof ?HibernateProxy)?{ ??
          96. ???????????????? return ? new ?HibernateBeanSerializer(returnValue).getProxy(); ??
          97. ????????????} else ? if (returnValue? instanceof ?PersistentCollection)?{ ??
          98. ???????????????? if (returnType.isAssignableFrom(Map. class ))?{ ??
          99. ????????????????????Map?proxyMap?=? new ?LinkedHashMap(); ??
          100. ????????????????????Map?map?=?(Map)returnValue; ??
          101. ????????????????????Set<Map.Entry>?entrySet?=?map.entrySet(); ??
          102. ???????????????????? for (Map.Entry?entry?:?entrySet)?{ ??
          103. ????????????????????????proxyMap.put(entry.getKey(),? new ?HibernateBeanSerializer(entry.getValue())); ??
          104. ????????????????????} ??
          105. ???????????????????? return ?proxyMap; ??
          106. ????????????????} ??
          107. ???????????????? ??
          108. ????????????????Collection?proxyCollection?=? null ; ??
          109. ???????????????? if (returnType.isAssignableFrom(Set. class ))?{ ??
          110. ????????????????????proxyCollection?=? new ?LinkedHashSet(); ??
          111. ????????????????} else ? if (returnType.isAssignableFrom(List. class ))?{ ??
          112. ????????????????????proxyCollection?=? new ?ArrayList(); ??
          113. ????????????????} else ?{ ??
          114. ???????????????????? return ?returnValue; ??
          115. ????????????????} ??
          116. ???????????????? ??
          117. ???????????????? for (Object?o?:?(Collection)returnValue)?{ ??
          118. ????????????????????proxyCollection.add( new ?HibernateBeanSerializer(o).getProxy()); ??
          119. ????????????????} ??
          120. ???????????????? return ?proxyCollection; ??
          121. ????????????} else ?{ ??
          122. ???????????????? return ?returnValue; ??
          123. ????????????} ??
          124. ????????} ??
          125. ? ??
          126. ???????? private ? boolean ?isExclude(MethodInvocation?mi,?String?propertyName) ??
          127. ???????????????? throws ?Throwable?{ ??
          128. ???????????? ??
          129. ???????????? for (String?excludePropertyName?:?excludesProperties)?{ ??
          130. ???????????????? if (propertyName.equals(excludePropertyName))?{ ??
          131. ???????????????????? return ? true ; ??
          132. ????????????????} ??
          133. ????????????} ??
          134. ???????????? ??
          135. ???????????? return ? false ; ??
          136. ????????} ??
          137. ???????? ??
          138. ???????? private ? static ?String?getPropertyName(String?methodName)?{ ??
          139. ????????????String?propertyName?=? null ; ??
          140. ???????????? if (methodName.startsWith( "get" ))?{ ??
          141. ????????????????propertyName?=?methodName.substring( "get" .length()); ??
          142. ????????????} else ? if (methodName.startsWith( "is" ))?{ ??
          143. ????????????????propertyName?=?methodName.substring( "is" .length()); ??
          144. ????????????} else ? if (methodName.startsWith( "set" ))?{ ??
          145. ????????????????propertyName?=?methodName.substring( "set" .length()); ??
          146. ????????????} ??
          147. ???????????? return ?propertyName?==? null ??? null ?:?StringUtils.uncapitalize(propertyName); ??
          148. ????????} ??
          149. ????} ??
          150. }??

          ?

          ?

          ?

          ?另這個類屬于rapid-framework的一部分,v2.0版本的flex RemoteObject將采用這個辦法.preview版本即將發(fā)布

          posted on 2008-10-31 00:33 badqiu 閱讀(3180) 評論(3)  編輯  收藏

          評論

          # re: 使用動態(tài)代理解決Hibernate序列化,避免延遲加載問題.  回復  更多評論   

          用了spring,你的方法就不行了吧
          2008-10-31 09:12 | lsqlister

          # re: 使用動態(tài)代理解決Hibernate序列化,避免延遲加載問題.  回復  更多評論   

          不用spring么?
          有spring用干嘛不用?重復發(fā)明輪子!!
          不過spring后面也是使用cglib生成動態(tài)代理,將以上代碼修改,可以改為只依賴cglib的Enhancer
          2008-10-31 09:26 | badqiu

          # re: 使用動態(tài)代理解決Hibernate序列化,避免延遲加載問題.  回復  更多評論   

          但這也是一種很有趣的解法。
          2008-11-01 17:07 | 金山詞霸2008

          只有注冊用戶登錄后才能發(fā)表評論。


          網站導航:
           
          主站蜘蛛池模板: 乌兰察布市| 阿坝| 航空| 新干县| 新密市| 玛纳斯县| 镇赉县| 万载县| 林周县| 三穗县| 罗甸县| 嘉祥县| 霍林郭勒市| 文水县| 吉木萨尔县| 正安县| 荣成市| 张家港市| 武清区| 邓州市| 临夏县| 章丘市| 太保市| 江津市| 托克托县| 佛山市| 都兰县| 呼伦贝尔市| 鹤庆县| 赤城县| 凤城市| 孟州市| 济宁市| 西华县| 合肥市| 百色市| 苍山县| 会同县| 海盐县| 阳泉市| 两当县|