[心缘地方]同学录
首页 | 功能说明 | 站长通知 | 最近更新 | 编码查看转换 | 代码下载 | 常见问题及讨论 | 《深入解析ASP核心技术》 | 王小鸭自动发工资条VBA版
登录系统:用户名: 密码: 如果要讨论问题,请先注册。

[备忘]CXF发布web service时,hibernate关系循环的问题

上一篇:[整理]flex的datagrid,一条记录时,data是null的问题的解决。
下一篇:[郁闷]Hibernate的级联删除到底怎么搞啊?

添加日期:2013/3/27 17:06:10 快速返回   返回列表 阅读4763次
两个bean,比如是1对多的关系
在hibernate的映射文件里,互相都映射的话,
CXF在生成soap的XML时会报这样的错:
org.apache.cxf.binding.soap.SoapFault: Marshalling Error: A cycle is detected in the object graph. This will cause infinitely deep XML

反正就是CXF发现是个圈,A找B,B找A,是个无限循环,所以报个错出来。

怎么解决呢?

有的说,这样:
@XmlTransient 
public Set<User> getUserSet() { 
return userSet; 

在引起循环的get方法上加个@XmlTransient,那么生成XML时就会忽略这步了,所以就不会循环了。

试了下,好像有时候有null的什么问题,稀里糊涂~~~

后来,找到这个方法:


public abstract class User implements CycleRecoverable{

//...
 public Object onCycleDetected(Context arg0) {
  Company temp = new Company ();
  temp.setId(id);
  return temp;
  }

}



也就是在可能引起循环的bean上,实现CycleRecoverable接口,
然后加一个onCycleDetected方法,return一个临时对象。
反正是个圈,随便搞一个对象,结束这个圈就行了。
验证,好使,OK~~~
==================================================
进一步实践发现,用onCycleDetected方法在数据较多时,仍然会引起循环。
比如多对多的关系时,A表数据1-->B表数据2-->A表数据3-->B表数据4,
由于是多对多的关系,乱成了一张网,却还没有循环,导致onCycleDetected方法得不到执行。


所以,仅仅用onCycleDetected方法还不够,还要配合@XmlTransient使用。

比如有ReportType类,它有getTypeItems()方法,也就是找所有的子记录。
@XmlTransient
public Set<ReportTypeItem> getTypeItems() {
    return typeItems;
}

用@XmlTransient的话,生成soap时,就会忽略getTypeItems()方法,
实际发送的数据中,就压根没有typeItems属性。
也就是取父的数据时,不取子数据,想取时,单独来个接口,取子的List就是了。
把所有的类似这种的父类中的get子List的方法都用@XmlTransient注掉就OK了,不会有循环引用的问题了。
==================================================
而在子类中,引用所属父类的属性,不要使用@XmlTransient。
如ReportType类有个version属性,表示它所属的版本对象。
ReportType类和Version类的关系,ReportType类就是子类了。
@XmlTransient
public Version getVersion() {
    return version;
}
如果使用了@XmlTransient,取得数据时,就不会有version属性了。
同时,更重要的一点,没有version属性了,
添加ReportType时,由于version没有值,就无法添加了。
说的比较晕,实际弄一下就明白了。
总之,这种反向引用父类的不要加XmlTransient。
====================================================
进一步,由于ReportType类有version属性了,而Version本身是一个类,
所以返回的数据是类似这样一个结构:
        <id xsi:nil=""true""/>
        <typeName>11</typeName>
        <typeNo>11</typeNo>
        <version>
          <active>0</active>
          <id>c3b3cde3416d41d9a50406bfd8d40485</id>
          <versionNumber>2</versionNumber>
        </version>
恭喜你,可能会遇到这样的错误:

ReferenceError: Error #1065: Variable Version is not defined.
at global/flash.utils::getDefinitionByName()

也就是变量Version没定义。

很晕,明明编译没错误,该有的都有,为什么报错呢~~~
弄了一天,终于明白个大概。
简单的说,就是返回的xml数据,Flex要把它恢复成类的形式,
也就是动态构建对象了,而这里的Version动态创建的时候,没找到类定义,
所以报错了。

原因是Flex编译器,对于没有实际使用的类,没给编译到swf中?
即使是import了,也不好使~~~~反正很晕。

解决办法就是:


import package.User;
private var _dummyUser:User; //声明一个变量
User; //或者更简单的,写个类名就行了。



还有重要的一点,要在application中声明,在模块module中写是不好使的。
======================================================"
 

评论 COMMENTS
没有评论 No Comments.

添加评论 Add new comment.
昵称 Name:
评论内容 Comment:
验证码(不区分大小写)
Validation Code:
(not case sensitive)
看不清?点这里换一张!(Change it here!)
 
评论由管理员查看后才能显示。the comment will be showed after it is checked by admin.
CopyRight © 心缘地方 2005-2999. All Rights Reserved