Grails中如何修改元类方法:移除集合toString的方括号
解决方案
Grails中通过hasMany定义的集合,实际是Hibernate的PersistentCollection实现(比如PersistentSet),这类集合是Hibernate动态生成的代理类,Groovy的ExpandoMetaClass无法直接覆盖其toString方法——代理会优先调用底层Hibernate实现的方法。
以下是几种可行的解决方法:
方法一:全局重写Object的toString兼容持久化集合
通过扩展Object的元类,判断实例是否为Hibernate持久化集合,再自定义输出格式:
def init = { servletContext -> ExpandoMetaClass.enableGlobally() Object.metaClass.toString = { def obj = delegate // 处理Hibernate持久化集合 if (obj instanceof org.hibernate.collection.spi.PersistentCollection) { // 避免懒加载未初始化的集合触发查询 if (!obj.wasInitialized()) { return 'Uninitialized Collection' } // 拼接集合元素为无方括号的字符串 obj.collect { it.toString() }.join(', ') } else { // 非集合类型调用原toString方法 obj.getClass().getMethod('toString').invoke(obj) } } }
方法二:针对实体类自定义集合输出
如果只需要处理特定实体的集合,可以在实体类中添加自定义方法,或者在集合初始化后重写其元类:
class SampleObject { static hasMany = [sampleList: SampleList] // 方法1:提供自定义的集合输出方法 String getSampleListText() { sampleList.collect { it.toString() }.join(', ') } // 方法2:在集合加载后重写其toString void afterLoad() { sampleList.metaClass.toString = { delegate.collect { it.toString() }.join(', ') } } }
方法三:使用Groovy扩展模块全局增强集合
创建Groovy扩展类,全局修改集合的toString行为:
// 新建src/main/groovy/CollectionExtensions.groovy class CollectionExtensions { static String toString(Collection self) { if (self instanceof org.hibernate.collection.spi.PersistentCollection) { if (!self.wasInitialized()) { return 'Uninitialized Collection' } self.collect { it.toString() }.join(', ') } else { // 对于普通集合,也可以自定义去掉方括号的格式 self.collect { it.toString() }.join(', ') } } } // 在Bootstrap中注册扩展 def init = { servletContext -> ExpandoMetaClass.enableGlobally() Collection.metaClass.mixin CollectionExtensions }
内容的提问来源于stack exchange,提问作者Victor Soares
相关产品推荐
相关产品推荐

