7

我有一个从 Hibernate 会话中获得的类的实例。那个会议早就过去了。现在,我正在打电话toString(),我得到了预期LazyInitializationException: could not initialize proxy - no Session,因为我试图访问 Hibernate 在加载实例期间没有解析的引用(延迟加载)。

我真的不想让加载变得急切,因为它会将查询从大约 120 个字符更改为超过 4KB(有 8 个连接)。而且我不必:我只想显示toString()被引用对象的 ID;即 Hibernate 在这个时间点需要知道的东西(或者它不能做延迟加载)。

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

4

4 回答 4

6

可以通过将 ID 字段的 accesstype 设置为“property”来做到这一点。像:

@Entity
public class Foo {
    // the id field is set to be property accessed
    @Id @GeneratedValue @AccessType("property")
    private long id;
    // other fields can use the field access type
    @Column private String stuff;
    public long getId() { return id; }
    public void setId(long id) { this.id = id; }
    String getStuff() { return stuff; }
    // NOTE: we don't need a setStuff method
}

这里解释了。这样,在创建代理时总是会填充 id 字段。

于 2009-11-12T14:21:38.210 回答
1

我找到了一种解决方法:

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)+")");
    }
}
于 2009-11-12T14:09:20.000 回答
1

我发现最适合良好实践的方法是修改此博客上的解决方案:http ://www.nonfunc.com/2016/02/05/jpa-performance-gotcha-tostring-really/ 。它需要对可空字段和 Collections 对象进行修改。

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());
}
于 2017-06-01T19:02:56.087 回答
0

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

编辑

如何使用 JPA 和 Hibernate 解决 LazyInitializationException

查看评论并进行一些搜索后,我相信这可能对您的方案最有利。

于 2009-11-12T13:13:58.020 回答