- 浏览: 187779 次
- 性别:
- 来自: 威海
文章分类
- 全部博客 (96)
- javascript (9)
- css (4)
- java (5)
- xml (1)
- dhtml (5)
- ajax (0)
- spring (0)
- 版本控制 (3)
- tomcat (0)
- web技术 (9)
- eclipse插件 (3)
- flex (9)
- android (3)
- 性能测试 (1)
- flash (4)
- Academic (4)
- EJB (2)
- JSF (0)
- ExtJS (2)
- ROR (9)
- linux (2)
- oracle (2)
- wtc (1)
- extjs4 (1)
- servlet (1)
- postgreSQL (3)
- OS (1)
- 线程 (1)
- unity3d (4)
- html (1)
- rvm (0)
最新评论
-
zxjlwt:
学习了。素人派http://surenpi.com
eclipse插件开发手记之编辑器上下文菜单 -
176170847:
你也遇到了?请问你怎么解决的啊?
flex swfloader 加载swf帧频变化 -
Kim_T:
我的完全没用 , 不知道怎么回事? 俩个地方我都设置了
svn忽略无关文件thumbs.db等 -
yiyanwan77:
babydeed 写道挺好的 建议弄成 chm格式的 呵呵 呵 ...
EXTJS4开发指南中文翻译 -
babydeed:
挺好的 建议弄成 chm格式的 呵呵
EXTJS4开发指南中文翻译
- 问题简单描述
项目中后台使用hibernate实现的jpa作为持久层,当blazeds解析返回数据包含未加载项时,触发了延迟加载动作,而此时事物已经结束,于是抛出session关闭异常。
- 解决思路
后台通过jpa返回的数据结果其实为动态代理创建的该类型的子类,调用这些对象的get方法时,动态代理子类的包装壳判断是否加载了数据(通过查看hibernate源码,可以得知有个initialized属性标记),如果没有,则查询该项。因此,只要避免转换时触发加载动作就可以解决该问题,简单想来有以下几种方案:
- aop切到最外的service层,得到返回结果,递归遍历属性,判断是否加载了属性(基本属性不存在这个问题)-注意,即使属性未加载,该属性值并不为空,而是一个代理对象),如果没有加载则想办法使其返回空(考虑过使用动态代理的方式,未能解决)
- 还是用aop,得到返回结果后,创建新的实例返回,依然要判断是否加载,如果已加载则返回真实值 (因为得到的对象为动态代理类,在对象为集合的时候获取实际类有点困难,我暂未能获知该途径,若有知情人,还望不吝赐教)
- 上面两种方案都需要增加递归遍历过程,对性能时有影响的,特别时第二种,所有属性都要重新创建,开销比较大。因此最佳方案应该时直接修改blazeds的源码,返回结果处理时,再用上述第一种方案的思路。
- 实现
因为项目时间上的压力,考虑从第一种方案入手,在实际解决的过程中仍然遇到了重重困难,无数次断点调试后发现了了如下规律:如果返回值为集合,则获取到的类名为PersistenceSet(实际上并非所有集合都是用Set代理 ),而如果为单个对象则类名中含有_$$_javasis..等内容(该规则与动态代理的实现有关),后来查看hibernate源码,发现代理其实为PersistentCollection或HibernateProxy接口的实现类,大部分问题都解决了,但是最后遇到子项加载父项时,如果直接置空属性,则将更新(此时session已经关闭,但实际上更新确成功了,这个现象一直没弄明白 ),尝试用动态代理解决,没有成功。最后,迫于项目时间压力,暂时再该期使用了第二种实现方式:
org.hibernate.collection.*
PersistentSet extends AbstractPersistentCollection implements java.util.Set AbstractPersistentCollection implements Serializable, PersistentCollection PersistentArrayHolder extends AbstractPersistentCollection PersistentBag extends AbstractPersistentCollection implements List PersistentElementHolder extends AbstractPersistentCollection PersistentIdentifierBag extends AbstractPersistentCollection implements List PersistentIndexedElementHolder extends AbstractPersistentCollection PersistentList extends AbstractPersistentCollection implements List PersistentListElementHolder extends PersistentIndexedElementHolder PersistentMap extends AbstractPersistentCollection implements Map PersistentMapElementHolder extends PersistentIndexedElementHolder PersistentSet extends AbstractPersistentCollection implements java.util.Set PersistentSortedMap extends PersistentMap implements SortedMap PersistentSortedSet extends PersistentSet implements SortedSet
LazyAspect.java
import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.beanutils.PropertyUtils; import org.apache.log4j.Logger; import org.aspectj.lang.ProceedingJoinPoint; import org.hibernate.collection.PersistentCollection; import org.hibernate.proxy.HibernateProxy; /** * 解决使用延迟加载配置,且service层返回时该项未加载时,blazeds抛出session关闭的问题 * * @author 王逸群 * @date 2011-10-8 */ public class LazyAspect { private static Logger log = Logger.getLogger(LazyAspect.class); public Object doAround(ProceedingJoinPoint pjp) throws Throwable { try { Object retVal = pjp.proceed(); Object safeObject = safeCopy(retVal); return safeObject; } catch (Exception e) { e.printStackTrace(); throw e; } } /** * 不触发延迟加载的深度拷贝 * * @param obj * 拷贝对象 * @return * @throws IllegalAccessException * @throws InvocationTargetException * @throws NoSuchMethodException * @throws InstantiationException */ public Object safeCopy(Object obj) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException, InstantiationException { return _safeCopy(obj, new HashMap<Object, Object>()); } /** * 不触发延迟加载的深度拷贝 * * @param obj * 拷贝对象 * @param copiedMap * @return * @throws IllegalAccessException * @throws InvocationTargetException * @throws NoSuchMethodException * @throws InstantiationException */ @SuppressWarnings({ "rawtypes", "unchecked" }) private Object _safeCopy(Object obj, Map<Object, Object> copiedMap) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException, InstantiationException { // 基本类型不可能为代理,直接返回 if (isPrimitive(obj)) { return obj; } // 如果已经解析,直接从map中获取 if (copiedMap.containsKey(obj)) { return copiedMap.get(obj); } Class clazz = obj.getClass(); // Collection对象 if (obj instanceof Collection) { Collection $collection = null; // PersistentCollection 代理 if (obj instanceof PersistentCollection) { PersistentCollection $persistentCollection = (PersistentCollection) obj; // 已经加载字段 if ($persistentCollection.wasInitialized()) { if ($persistentCollection instanceof Set) { //暂无法获取集合实际类 $collection = new HashSet(); } else if ($persistentCollection instanceof List) { //暂无法获取集合实际类 $collection = new ArrayList(); } } // 未加载 else { copiedMap.put(obj, null); return null; } } // 非PersistentCollection代理集合 else { $collection = (Collection) obj.getClass().newInstance(); } Iterator itr = ((Collection) obj).iterator(); if (itr != null) while (itr.hasNext()) { $collection.add(_safeCopy(itr.next(), copiedMap)); } copiedMap.put(obj, $collection); return $collection; } // Map else if (obj instanceof Map) { Map $map = null; Map map = (Map) obj; // 代理 if (obj instanceof PersistentCollection) { PersistentCollection $persistentCollection = (PersistentCollection) obj; // 已加载 if ($persistentCollection.wasInitialized()) { //暂无法获取集合实际类 $map = new HashMap(); } // 未加载 else { copiedMap.put(obj, null); return null; } } // 非代理对象 else { $map = (Map) obj.getClass().newInstance(); } for (Object ele : map.keySet()) { $map.put(ele, _safeCopy(map.get(ele), copiedMap)); } copiedMap.put(obj, $map); return $map; } // 数组 else if (clazz.isArray()) { int len = Array.getLength(obj); if (len > 0) { String arrClassName=clazz.getName(); String className=arrClassName.substring(arrClassName.indexOf("L")+1,arrClassName.length()-1); // 注意,这里创建的实例非Array Object $arr = Array.newInstance(Class.forName(className), len); for (int i = 0; i < len; i++) { Array.set($arr, i, _safeCopy(Array.get(obj, i), copiedMap)); } copiedMap.put(obj, $arr); return $arr; } else { copiedMap.put(obj, null); return null; } } // 代理 if (obj instanceof HibernateProxy) { HibernateProxy proxy = (HibernateProxy) obj; // 已加载 if (!proxy.getHibernateLazyInitializer().isUninitialized()) { Object $obj = _safeCopy(proxy.getHibernateLazyInitializer() .getImplementation(), copiedMap); copiedMap.put(obj, $obj); return $obj; } // 未加载 else { copiedMap.put(obj, null); return null; } } // 普通类 else { Object $obj = obj.getClass().newInstance(); copiedMap.put(obj, $obj); // 解析属性 Field[] fields = obj.getClass().getDeclaredFields(); for (Field field : fields) { String subFieldName = field.getName(); Object fieldValue = null; // 类中可能有不可读属性(指非标准setter,getter访问方式),比如public static if(PropertyUtils.isReadable(obj, subFieldName)){ fieldValue = PropertyUtils.getProperty(obj, subFieldName); } // 属性值为空或者无法读取的不处理 if (fieldValue != null) { PropertyUtils.setProperty($obj, subFieldName, _safeCopy(fieldValue, copiedMap)); } } return $obj; } } /** * 是否为基本类型,注意,与jdk api中的isPrimitive规则不同 * * @param obj * @return */ public boolean isPrimitive(Object obj) { if (obj == null) { return true; } Class clazz = obj.getClass(); if (clazz.isPrimitive()) { return true; } String className = clazz.getName(); return className.indexOf("java") == 0 && (!(obj instanceof Collection)) && (!(obj instanceof Map)) && (!clazz.isArray()); } }
发表评论
-
flex mx:image 在vbox中设置mxHeight依然占位
2012-09-09 16:21 1324<mx:VBox > <m ... -
flash同一个图层创建的按钮无法响应事件
2012-07-30 22:40 921遇到个怪现象,flash一个图层中有多个元素,其中一个做成了按 ... -
flex swfloader 加载swf帧频变化
2012-07-30 22:37 933求解 -
flex FormItem
2011-09-16 16:06 802FormItem831.FormItemSkin832.con ... -
Flex Module静态方法
2011-09-03 15:27 1124在java中使用静态方法提供api是很自然的事情,但在Flex ... -
Flex的静态变量
2011-09-03 15:18 1819主程序App.mxml Module1:A.mxml M ... -
flex 特效
2010-09-17 15:51 1091公司第四个产品大体功能已经开发出来了,接下来的工作很大一 ... -
Flex Cairngorm
2009-08-22 17:22 1229我学Flex Cairngorm-1,Cairngorm概览 ... -
ANT
2009-02-18 16:37 1716ANT 关键字: ant ... -
iframe多帧交互
2009-01-16 14:08 8161:同源策略 2:top指向顶级窗口 3:self==wind ... -
iframe总结
2009-01-12 11:23 1692IFrame语法小全 IFrame语法小全 IFrame可以 ... -
自定义标签
2009-01-08 08:34 1326标准JSP标签是用来调用JavaBean组件的操作,处理定向请 ... -
写自定义标签时标记attribute里rtexprvalue的用法
2009-01-06 09:03 1066写自定义标签时标记attribute里rtexprvalue的 ... -
JavaScript Core Index
2009-01-05 20:21 866JavaScript Core Index Below ... -
Aptana使用入门一:Code Assist
2009-01-05 20:15 2443Aptana使用入门一:Code Assist 2008-03 ... -
32款实用源码编辑器一览
2009-01-05 20:12 393632款实用源码编辑器一览(一) 编译:四眼天兔 原文出 ...
相关推荐
标题中的“PureMVC+Flex+BlazeDS+Spring+Hibernate.doc”指的是一项整合了多种技术的Web应用开发方案,这些技术包括PureMVC、Flex、BlazeDS、Spring和Hibernate。这篇文档可能是指导读者如何将这些技术结合在一起...
综上所述,这个在线书店的开发实例结合了Flex 4.6的富用户体验、BlazeDS的数据通信能力、Spring 3的依赖注入和业务管理、JPA的持久化机制以及Hibernate和MySQL的数据库支持。通过学习和实践这个项目,你将能够掌握...
【标题】"Flex4.X+BlazeDS+Spring3实战开发在线书店四"涉及的核心技术栈是Adobe Flex 4.6、BlazeDS、Spring 3框架以及Java相关的JPA和Hibernate,配合MySQL数据库实现一个在线书店的完整系统。下面将详细阐述这些...
在“Flex4+BlazeDS+Spring+Hibernate 整合源码”中,开发者可能实现了以下功能: 1. 使用Flex4创建前端用户界面,包括自定义组件和动画效果。 2. 通过BlazeDS配置,实现在Flex客户端与Spring服务层之间的数据双向...
《Flex4.X+BlazeDS+Spring3 实战开发在线书店》是一门深入探讨使用Adobe Flex 4.6、BlazeDS、Spring 3框架以及Java相关技术进行Web应用程序开发的课程。这门课程旨在帮助开发者掌握如何构建功能丰富的、交互性强的...
标题中的“PureMVC+Flex+BlazeDS+Spring+Hibernate”是一个常见的技术栈组合,用于构建企业级的 Rich Internet Applications (RIA)。这个技术栈包括前端开发框架、后端服务通讯、应用服务器、服务端架构和数据持久化...
集成Flex4、BlazeDS、Spring和Hibernate可以构建出高度互动的前端和强大后端相结合的Web应用。这种架构使得开发人员可以充分利用Flex的富客户端能力,同时利用Spring和Hibernate的强大功能处理业务逻辑和数据库操作...
总结一下,"Myeclipse6.5+flex3+Blazeds+spring+hibernate完美整合源代码"代表了一个完整的、成熟的开发解决方案,它结合了现代Web开发的多个关键组件,提供了从前端用户界面到后端数据存储的全面支持。配合相应的...
在IT领域,构建高效、可扩展的Web应用是至关重要的,而"spring+springMVC+jpa+hibernate框架整合"就是一个常见的解决方案。这个整合涉及到四个关键的技术栈:Spring框架、SpringMVC、JPA(Java Persistence API)...
Flex+Spring+Hibernate示例是一种常见的企业级应用架构,它结合了Adobe Flex前端技术、Spring后端框架和Hibernate持久层框架,以构建高效、灵活且易于维护的Web应用程序。在这个示例中,开发者可能已经展示了如何...
**Spring MVC + JPA(Hibernate4) + Redis + ActiveMQ:构建高效、全面的Web应用** Spring MVC 是Spring框架的一部分,专门用于构建Web应用程序的模型-视图-控制器(MVC)架构。它提供了一个灵活的请求处理机制,...
"spring3+springmvc+jpa+hibernate多数据源"是一个示例项目,它演示了如何在一个应用中集成Spring 3、Spring MVC、JPA 2.0以及Hibernate,以实现对多个数据源的支持。下面将详细介绍这些技术及其集成的关键点。 **...
在本项目中,Spring被用来整合其他技术,如Jersey、JPA和Hibernate,以实现一个完整的Web服务解决方案。 Jersey是Java RESTful Web Services(RESTful API)的实现,它基于JSR 311和JSR 339标准。通过使用Jersey,...
在IT行业中,构建一个基于Spring、SpringMVC、Hibernate和JPA的开发环境是常见的任务,这四个组件都是Java企业级应用开发中的重要工具。让我们深入探讨这些技术以及如何将它们整合在一起搭建一个完整的开发环境。 *...
标题“Spring + JPA + Hibernate配置”涉及到的是Java开发中常用的三个框架——Spring、Java Persistence API (JPA) 和Hibernate的集成与配置。这是一份关于如何将这些框架结合使用的教程或参考资料,可能包含了实现...
通过使用AMF(Action Message Format)协议,BlazeDs能够实现低延迟、高效率的数据传输,使得Flex应用能够与Java服务进行实时通信。 Spring框架是Java领域中广泛使用的轻量级应用框架,它简化了Java企业级应用的...
《Flex+Java+Spring+Hibernate+BlazeDS整合详解》 在现代的Web开发中,Flex作为客户端的富互联网应用程序(RIA)框架,与Java、Spring、Hibernate等后端技术结合,可以构建出高效、交互性强的Web应用。本文将详细...
Flex+Blazeds+Spring+Hibernate+MySQL是一个经典的Java企业级开发组合,它结合了前端的富互联网应用程序(RIA)开发框架Flex与后端的强大数据处理能力,通过Blazeds作为中间层通信桥梁,利用Spring进行服务管理和...
在"基于Flex4.X+BlazeDS+Spring3+JPA+Hibernate+MySQL实战开发在线二.exe"这个文件中,很可能是项目的源代码或者是一个可执行程序,它展示了如何整合所有这些技术。MySQL是常用的开源关系型数据库,用于存储和管理...