有很多同學在用使用flex+hibernate做應用開發時都會出現由延遲加載導致的異常:Could not initialize proxy…………….
筆者在使用ibatis2.x做持久層時,也遇到這個問題,究其原因,在于blazeds無法正常序列化Java端返回的代理類。
而hibernate默認會對類屬性和集合屬性返回代理,在大多數情況下這都是很合理的,即使要在web端訪問代理屬性,也可以采用openSessionInView模式,將session延伸到web層。但是flex的客戶端比較特殊,不宜采取這種做法。針對這個問題,有一些開源的解決方案:dpHibernate,Glead等,但筆者感覺這些框架侵入性太強,不宜采用。
在不引入第三方框架的情況下,可以采取兩個辦法:1.增加一層Vo類,將類屬性和集合屬性的代理進行轉化,然后與as映射,傳給flex端 ,這樣序列化是ok的。
2.采用Spring 的aop解決方案,對可能返回無法正常序列化的pojo方法進行攔截。步驟如下:
1.開啟@AspectJ
<aop:aspectj-autoproxy/>
2.編寫針對具有代理屬性類的轉化工具類:假如Student類具有多對一的類屬性Grade:
public class Student { private Long id; private Grade grade; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public Grade getGrade() { return grade; } public void setGrade(Grade grade) { this.grade = grade; } }
用代碼生成器生成StudentConvert.java :
public class StudentConverter { public static Student convert2Student(Object sourceObj) { Student source=(Student) sourceObj; Student target = new Student(); target.setId(source.getId()); //Hibernate.initialize(source.getGrade()); 可以選擇將類或集合代理初始化 //target.setGrade(source.getGrade()); return target; } public static List convert2StudentList(List oldlist) { List newlist= new ArrayList(); for(Object sourceObj : oldlist) { newlist.add(convert2Student(sourceObj)); } return newlist; } }
3.編寫aop的advisor進行環繞通知,假設StudentDao 有兩個方法
Student findById(Long id)
List findAll();
由代碼生成器生成對應的advisor如下 HibernateAdvisor.java :
@Aspect public class HibernateAdvisor { //insert aop code for hibernate /////////////////////////// // Student readme /////////////////////////// /** * 必須為final String類型的,注解里要使用的變量只能是靜態常量類型的 */ // 切入點定義 public static final String StudentList = "execution(* com.lai.flex.service.StudentDao.findAll(..))"; public static final String Student = "execution(* com.lai.flex.service.StudentDao.findBy*(..))"; @Around(StudentList) public List convertStudentList(ProceedingJoinPoint joinPoint) { //System.out.println("Convert之前"); Object[] args = joinPoint.getArgs(); Object obj = null; List newlist= null; try { obj = joinPoint.proceed(args); List old= (List) obj; newlist=(StudentConverter.convert2StudentList(oldlist)); } catch (Throwable e) { e.printStackTrace(); } //System.out.println("Convert之后"); // 方法執行后的代理處理 return newlist; } @Around(Student) public Student convertStudent(ProceedingJoinPoint joinPoint) { //System.out.println("Convert之前"); Object[] args = joinPoint.getArgs(); Object obj = null; Student newsStudent = null; try { obj = joinPoint.proceed(args); newsStudent = StudentConverter.convert2Student(obj); } catch (Throwable e) { e.printStackTrace(); } //System.out.println("Convert之后"); // 方法執行后的代理處理 return newsStudent; } // generator-insert-location }
最后,由StudentDao方法返回的代理類和集合屬性在序列化到flex端之前,都被攔截,進行轉化后,可以正常序列化了。
聲明:如需轉載,請注明作者-hhlai1990@gmail.com
歡迎大家使用rapid-framework快速開發框架以及rapid-generator代碼生成器
http://code.google.com/p/rapid-framework