【问题标题】:How to convert javassist instance into instance of a specific domain如何将 javassist 实例转换为特定域的实例
【发布时间】:2012-07-26 09:33:49
【问题描述】:

我想使用 grails 1.3.7 将两个特定域类的实例列表相交。

问题是,一个列表的实例是由 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 的元素类型是 Bar_$$_javassist_139bars 的元素类型是 Bar,所以 intersectedBars 总是 []

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

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

什么是更好的解决方案?

我怎样才能将Bar_$$_javassist_139 转换为Bar 以便intersect() 正常工作?

【问题讨论】:

    标签: grails grails-orm


    【解决方案1】:

    这取决于你实际上想要做什么。 intersect 方法最终依赖于equals,所以如果你在Bar 中实现equalshashCode,那么它会做你想做的事。但是您通常不应该根据对象 ID 实现 equals,因为仅在保存对象时分配 ID,因此您无法将新创建的对象与以前保存的对象进行比较。 Hibernate 建议您implement it based on a business key(不是生成的 ID,但在对象的整个生命周期内稳定且不太可能更改)

    class UserAccount {
      String username
      String realname
    
      public boolean equals(that) {
        return ((that instanceof UserAccount)
            && (this.username == that.username))
      }
    
      public int hashCode() {
        username.hashCode()
      }
    }
    

    因此,如果您确实想要进行 ID 比较,那么明确地进行比较会更清楚。

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

    【讨论】:

    • 这里的ID比较就足够了。尽管如此,还是可以强制转换 javassist 类?
    • javassist 代理 isinstanceof Bar,关键是 ID 为 5 的 Bar 的代理不是同一个对象(== 在Java 意义)为Bar.get(5)。有GrailsHibernateUtil.unwrapIfProxy,但除非确实必须这样做,否则不应显式解包代理,因为这样做会导致对数据库进行额外的 SQL 查询。
    猜你喜欢
    • 1970-01-01
    • 2015-05-29
    • 1970-01-01
    • 2020-07-14
    • 1970-01-01
    • 2021-08-21
    • 1970-01-01
    • 2015-12-12
    • 1970-01-01
    相关资源
    最近更新 更多