2012-07-26 48 views
2

我想使用grails 1.3.7来交叉两个特定域类的实例列表。如何将javassist实例转换为特定域的实例

问题是,一个列表的实例是由javasisst创建的,所以交集的结果总是一个空列表。

这里是我的域:

class User { 
    ... 
    static hasMany = [foos : Foo] 
    ... 
} 

class Foo { 
    ... 
    static hasMany = [bars : Bar] 
    ... 
} 

class Bar { 
    ... 
    static hasMany = [localizedTitles : LocalizedTitle] 
    ... 
} 

我得到了用户的所有Bar情况下,像这样的列表:

def allBarsOfUser = userInstance.foos.bars.flatten() 

,并尝试与Bar实例的另一个列表相交:

def intersectedBars = bars.intersect(allBarsOfUser) 

问题是,元素的类型allBarsOfUser ist Bar_$$_javassist_139而且bars的元素的类型是Bar因此intersectedBars总是[]

我解决了通过执行以下操作我的问题 - 但我不喜欢的解决方案:

def allBarsOfUser = userInstance.foos.bars.flatten().collect{Bar.get(it.id)} 

什么会是一个更好的解决办法?

我怎么能投Bar_$$_javassist_139Bar,以便intersect()工作正常?

回答

1

这取决于你实际要做的事情。 intersect方法最终依赖于equals,因此如果您在Bar中实施equalshashCode,那么它将执行您想要的操作。但是您通常不应该在对象ID方面实现equals,因为只有在保存对象时才会分配ID,因此您无法将新创建的对象与先前保存的对象进行比较。休眠建议您implement it based on a business key

class UserAccount { 
    String username 
    String realname 

    public boolean equals(that) { 
    return ((that instanceof UserAccount) 
     && (this.username == that.username)) 
    } 

    public int hashCode() { 
    username.hashCode() 
    } 
} 

所以,如果你想要一个ID比较那么它的更清楚这样做(的东西,是不是生成的ID,但它是稳定的,不可能在整个对象的生命周期变化)明确。

def userBarIds = allBarsOfUser*.id 
def intersectedBars = bars.findAll { it.id in userBarIds } 
+0

这里的ID比较就足够了。然而,可以施放一个javassist类吗? – aiolos 2012-07-26 12:44:33

+5

javassist代理_is_是一个'instanceof Bar',问题是代码为'Bar'且ID为5的Bar.get(5)不是同一个对象(Java意义上的'==')' 。有'GrailsHibernateUtil.unwrapIfProxy',但你不应该明确地展开代理,除非你真的必须这样做会导致对数据库的额外的SQL查询。 – 2012-07-26 13:02:30

相关问题