该帖已经被评为新手帖
|
|
---|---|
作者 | 正文 |
发表时间:2009-05-26
最后修改:2009-06-02
/** * 判断当前流程实例上下文中,是否存在Blocking(阻挡性)的任务 * 规则 * 1.任务未结束 * 2.任务是必办理的 * 3.当前任务实例的token和执行上下文的token一致 * @param token * @return */ public boolean hasBlockingTaskInstances(FlowToken token) { boolean hasBlockingTasks = false; System.out.println("LOC_1 :" + token.getId()); Set<TaskInstance> taskInstances = flowInstance.getTaskInstances(); if (taskInstances!=null) { Iterator<TaskInstance> iter = taskInstances.iterator(); while ( (iter.hasNext()) && (!hasBlockingTasks)) { System.out.println("LOC_2 : " + taskInstance.getFlowToken().getId()); System.out.println("LOC_3 : " + token == taskInstance.getFlowToken()); System.out.println("LOC_4 : " + token.equals(taskInstance.getFlowToken()); TaskInstance taskInstance = (TaskInstance) iter.next(); if ( (! taskInstance.hasEnded()) //任务未结束 && (taskInstance.getIsBlocking()) //任务是必办理的 && (token!=null) && (token.equals(taskInstance.getFlowToken())) ) { hasBlockingTasks = true; } } } return hasBlockingTasks; } 上述的 LOC_1 处和 LOC_2 处打印的ID完全相等, LOC_3处输出true(说明对象地址相同),BUT~~ LOC_4处输出是false; 给出FlowToken的equals实现 /* (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (!(obj instanceof FlowToken)) return false; final FlowToken other = (FlowToken) obj; if (id == null || other.id == null) { return false; } else if (!id.equals(other.id)) return false; return true; } 跟踪发现,实际进入equals的obj参数根本不是外面传入的那个token对象,中间过程被Hinernate的CGLIBLazyInitializer做了代理处理,发生了底层对象的变换。 开始大家都打死不信有这样的BUG,经过对jvm线程和变量编号的反复跟踪,BUG每次都重现。确认CGLIBLazyInitializer确有问题,但目前在国内互联网上没有找到相同的案例。这里提出,供javaeye上的大牛商讨! 如果我们一群人的诊断是对的,hibernate就隐藏了一个相当恐怖的bug咯!!! 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2009-05-26
补充一下,这样的bug为啥会发生,出现几率如何,目前完全是一抹黑。望各位共同关注
|
|
返回顶楼 | |
发表时间:2009-05-26
?
equals不是hibernate的注意事项中说得很清楚,如果要用到,需要自己重载,否则就不要通过equals来判断是否equal了。 |
|
返回顶楼 | |
发表时间:2009-05-26
LZ 用的是最新版本?
|
|
返回顶楼 | |
发表时间:2009-05-26
麻烦把 import 部分发一下。
|
|
返回顶楼 | |
发表时间:2009-05-27
严格来说,这个还没研究过!!
|
|
返回顶楼 | |
发表时间:2009-05-27
jianfeng008cn 写道 ?
equals不是hibernate的注意事项中说得很清楚,如果要用到,需要自己重载,否则就不要通过equals来判断是否equal了。 我上面的那段equals代码还不算重载嘛?应该是已经对bean的equals做了自己的实现了啊,请教一下啊! |
|
返回顶楼 | |
发表时间:2009-05-27
linliangyi2007 写道 代码如下:
/** * 判断当前流程实例上下文中,是否存在Blocking(阻挡性)的任务 * 规则 * 1.任务未结束 * 2.任务是必办理的 * 3.当前任务实例的token和执行上下文的token一致 * @param token * @return */ public boolean hasBlockingTaskInstances(FlowToken token) { boolean hasBlockingTasks = false; System.out.println("LOC_1 :" + token.getId()); Set<TaskInstance> taskInstances = flowInstance.getTaskInstances(); if (taskInstances!=null) { Iterator<TaskInstance> iter = taskInstances.iterator(); while ( (iter.hasNext()) && (!hasBlockingTasks)) { System.out.println("LOC_2 : " + taskInstance.getFlowToken().getId()); System.out.println("LOC_3 : " + token == taskInstance.getFlowToken()); System.out.println("LOC_4 : " + token.equals(taskInstance.getFlowToken()); TaskInstance taskInstance = (TaskInstance) iter.next(); if ( (! taskInstance.hasEnded()) //任务未结束 && (taskInstance.getIsBlocking()) //任务是必办理的 && (token!=null) && (token.equals(taskInstance.getFlowToken())) ) { hasBlockingTasks = true; } } } return hasBlockingTasks; } 上述的 LOC_1 处和 LOC_2 处打印的ID完全相等, LOC_3处输出true(说明对象地址相同),BUT~~ LOC_4处输出是false; 给出FlowToken的equals实现 /* (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (!(obj instanceof FlowToken)) return false; final FlowToken other = (FlowToken) obj; if (id == null || other.id == null) { return false; } else if (!id.equals(other.id)) return false; return true; } 跟踪发现,实际进入equals的obj参数根本不是外面传入的那个token对象,中间过程被Hinernate的CGLIBLazyInitializer做了代理处理,发生了底层对象的变换。 开始大家都打死不信有这样的BUG,经过对jvm线程和变量编号的反复跟踪,BUG每次都重现。确认CGLIBLazyInitializer确有问题,但目前在国内互联网上没有找到相同的案例。这里提出,供javaeye上的大牛商讨! 如果我们一群人的诊断是对的,hibernate就隐藏了一个相当恐怖的bug咯!!! session.load 这类方法本来就返回的Cglib代理你不会刚知道吧 来分析下equals public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; // 以上2条可以不用测试if (!(obj instanceof FlowToken)) return false; // System.out.println(obj.getClass()) 正确返回Cglib代理 这条正确通过 final FlowToken other = (FlowToken) obj; // 问题来了 other.id? 难道你用的public Integer id? if (id == null || other.id == null) { // 就是这条出错了 // 测试结果id=0 return false; } else if (!id.equals(other.id)) return false; return true; } 原因分析: 当一个类实例传入到另一个同类型的类中可以直接调用他的private字段 p.setId(1); public void setPeople(People p) { p.id=100; System.out.println(p.id); //输出100 System.out.println(p.getId()); //输出1 } 具体为什么我也从来没在什么地方看到过,希望了解的指点一下 所以other.id是问题的关键 other.getId()看看 |
|
返回顶楼 | |
发表时间:2009-05-27
jianfeng008cn 写道 麻烦把 import 部分发一下。
import java.sql.Timestamp; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import com.shine.wfm.WfmConfiguration; import com.shine.wfm.WfmContext; import com.shine.wfm.db.AsynJobSession; import com.shine.wfm.db.HibernateSessionFactory; import com.shine.wfm.def.FlowDefine; import com.shine.wfm.def.Node; import com.shine.wfm.def.Transition; /** * 流程执行令牌对象 * * @author 林良益 * 2008-06-27 * @version 1.0 */ public class FlowToken implements java.io.Serializable { |
|
返回顶楼 | |
发表时间:2009-05-27
最后修改:2009-05-27
jianfeng008cn 写道 麻烦把 import 部分发一下。
页面更新了没看到,和上面同学一样,我想说的是cgilb增强时正常现象,至于为什么不能equal,我也不知道。 |
|
返回顶楼 | |