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