如何在使用Hibernate映射的类中实现toString()?

如何在使用Hibernate映射的类中实现toString()?,hibernate,lazy-loading,tostring,Hibernate,Lazy Loading,Tostring,我有一个从Hibernate会话中获得的类的实例。那次会议早就结束了。现在,我正在调用toString()并得到预期的LazyInitializationException:无法初始化代理-无会话,因为我试图访问Hibernate在加载实例(延迟加载)期间未解析的引用 我真的不想让加载变得急促,因为它会将查询从大约120个字符更改为超过4KB(有8个连接)。我不必这样做:我只想在toString()中显示被引用对象的ID;i、 e.Hibernate此时需要知道的事情(或者它不能进行延迟加载)

我有一个从Hibernate会话中获得的类的实例。那次会议早就结束了。现在,我正在调用
toString()
并得到预期的
LazyInitializationException:无法初始化代理-无会话
,因为我试图访问Hibernate在加载实例(延迟加载)期间未解析的引用

我真的不想让加载变得急促,因为它会将查询从大约120个字符更改为超过4KB(有8个连接)。我不必这样做:我只想在
toString()
中显示被引用对象的ID;i、 e.Hibernate此时需要知道的事情(或者它不能进行延迟加载)


所以我的问题是:你如何处理这个案子?切勿尝试使用
toString()中的引用。
?或者在加载代码时调用
toString()
,以防万一?或者Hibernate中是否有一些实用函数,当我向它传递一个可能是惰性的引用时,它将返回一些有用的东西?或者您完全避免在
toString()
中引用吗?

如果您只想返回对象的ID,我想调用getID(),然后解析int/long,只要在您希望显示它的那一刻使用字符串值就可以了。至少从这个问题来看是这样的

编辑


查看评论并进行搜索后,我认为这可能对您的场景最为有利。

我找到了一个解决方法:

public static String getId (DBObject dbo)
{
    if (dbo == null)
        return "null";

    if (dbo instanceof HibernateProxy)
    {
        HibernateProxy proxy = (HibernateProxy)dbo;
        LazyInitializer li = proxy.getHibernateLazyInitializer();
        return li.getIdentifier ().toString ();
    }

    try
    {
        return Long.toString (dbo.id ());
    }
    catch (RuntimeException e)
    {
        return "???";
    }
}
因此,这段代码的作用是从对象中获取ID(64位数字)
DBObject
是一个定义
long id()
的接口。如果对象是Hibernate代理,那么我与它的
LazyInitializer
对话以获取ID。否则,我调用
ID()
。用法:

class Parent {
    DBObject child;
    public String toString () {
        return "Parent (id=..., child=" + getId(child)+")");
    }
}

可以通过将ID字段的accesstype设置为“property”来实现这一点。比如:

已经解释过了。
这样,在创建代理时,id字段总是被填充。

我发现最适合良好实践的方法是修改此博客上的解决方案:。它需要修改可为null的字段和集合对象

public toString() {
  return String.format("FuBar [id=%d" +  
      + ", fu=%s" // fu is a lazy non-nullable field
      + ", bar=%s" // bar is a nullable lazy field
      + ", borks=%s]", // borks is a lazy collection of Bork objects
      id,
      fu instanceof HibernateProxy ? "[null]" : bar.toString(),
      bar == null || bar instanceof HibernateProxy ? "[null]" : bar.toString(),
      borks instanceof PersistentSet ? "[null]" : borks.toString());
}

如果Java有闭包,您可以执行以下操作:String x=lazyToString({=>this.getY()})+lazyToString({=>this.getZ()});并用懒散的方法捕捉期望。内部类(或try/catch)的开销太高,无法实现这一点。是的,但这也不会给我一个会话。没错。您不仅可以打印未加载的值。我以为这就是目的。您将无法启动会话并关联toString方法调用上的对象。我的观点是,此信息必须在某个地方可用(请参阅下面的答案):)这将引发LazyInitializationException,因为引用尚未解析。Aaron,在阅读此评论后,我编辑了我的帖子。请查看新信息,并让我知道这是否解决了问题。@Woot-答案没有帮助。惰性初始化值将永远不会被读取。发送已提交。连接已关闭。是的,我看到事务已提交。然而,在帖子中,有可能重构现有代码以使用此处找到的OpenSessionInView模式:如果这在Aaron的环境中不可行,那就这样吧。@Woot:我必须同意Thomas的观点。+1我喜欢它;这里有一个小问题:我使用的是DSL语法,所以我的getter名为“id()”,而不是“getId()”。我想我可以为这个特殊情况添加第二个getter,但也许可以告诉Hibernate getter的名称?好吧,可以创建自己的org.Hibernate.property.PropertyAccessor实现,并将完全限定的名称声明为@AccessType的值。另一方面,您可以创建setter(您也需要它)和getter并将它们设置为私有,这样您就不会在应用程序的其余部分看到它们了。@EJB:它真的工作了吗?我有一种情况,类a------>(有一对多关系)和类B。a和B都有多个属性。因此,当我对类a执行toString()方法调用时,尽管为类a的Id字段设置了@AccessType(“property”),但由于LazyInitialization异常(如上所述)而失败。我知道您在那里做了什么。一些评论:混合使用
String.format()
+
对性能有害。您还应该将
[null]
替换为
,因为代理不是null-只是没有加载。更好的方法是返回
,其中
TYPE
是实体类型,
ID
是主键。这个例子并不完全是我所拥有的,变量和字符串的连接确实会影响性能(格式字符串应该编译成静态字符串),但我认为为toString的性能而汗流浃背并不是特别重要,因为它将用于调试或错误报告,在生产环境中不应超频繁调用。不过,我喜欢指定lazy vs null的建议。
public toString() {
  return String.format("FuBar [id=%d" +  
      + ", fu=%s" // fu is a lazy non-nullable field
      + ", bar=%s" // bar is a nullable lazy field
      + ", borks=%s]", // borks is a lazy collection of Bork objects
      id,
      fu instanceof HibernateProxy ? "[null]" : bar.toString(),
      bar == null || bar instanceof HibernateProxy ? "[null]" : bar.toString(),
      borks instanceof PersistentSet ? "[null]" : borks.toString());
}