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

发布于 2024-08-11 03:55:28 字数 485 浏览 4 评论 0原文

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

我真的不想让加载急切,因为它会将查询从大约 120 个字符更改为超过 4KB(有 8 个连接)。我不必这样做:我想在 toString() 中显示的只是所引用对象的 ID;即 Hibernate 此时需要知道的事情(否则它无法执行延迟加载)。

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

I have an instance of a class that I got from a Hibernate session. That session is long gone. Now, I'm calling toString() and I'm getting the expected LazyInitializationException: could not initialize proxy - no Session since I'm trying to access a reference which Hibernate didn't resolve during loading of the instance (lazy loading).

I don't really want to make the loading eager since it would change the query from about 120 characters to over 4KB (with eight joins). And I don't have to: All I want to display in toString() is the ID of the referenced object; i.e. something that Hibernate needs to know at this point in time (or it couldn't do the lazy loading).

So my question: How do you handle this case? Never try to use references in toString()? Or do you call toString() in the loading code just in case? Or is there some utility function in Hibernate which will return something useful when I pass it a reference which might be lazy? Or do you avoid references in toString() altogether?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

全部不再 2024-08-18 03:55:28

可以通过将 ID 字段的访问类型设置为“属性”来实现此目的。例如:

@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 字段。

It's possible to do this by setting the accesstype of the ID field to "property". like:

@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
}

It's explained here.
This way the id field is allways populated when a proxy is created.

挽你眉间 2024-08-18 03:55:28

我找到了一个解决方法:

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)+")");
    }
}

I've found a workaround:

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 "???";
    }
}

So what this code does is it fetches the ID (a 64bit number) from the object. DBObject is an interface which defines long id(). If the object is a Hibernate proxy, then I talk to its LazyInitializer to get the ID. Otherwise, I call id(). Usage:

class Parent {
    DBObject child;
    public String toString () {
        return "Parent (id=..., child=" + getId(child)+")");
    }
}
风情万种。 2024-08-18 03:55:28

我发现最适合良好实践的方法是对此博客上找到的解决方案进行修改: http://www.nonfunc.com/2016/02/05/jpa-performance-gotcha-tostring-really/。它需要对可为 null 的字段和 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]" : fu.toString(),
      bar == null || bar instanceof HibernateProxy ? "[null]" : bar.toString(),
      borks instanceof PersistentSet ? "[null]" : borks.toString());
}

I've found the way that best fits good practice is a modification of the solution found on this blog: http://www.nonfunc.com/2016/02/05/jpa-performance-gotcha-tostring-really/. It needed modification for nullable fields and for Collections objects.

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]" : fu.toString(),
      bar == null || bar instanceof HibernateProxy ? "[null]" : bar.toString(),
      borks instanceof PersistentSet ? "[null]" : borks.toString());
}
迷爱 2024-08-18 03:55:28

如果您想要返回的只是对象的 ID,我想调用 getID(),然后在您希望显示时将 int/long 解析为 String 值就可以了。至少根据这个问题看起来是这样。

编辑

如何使用 JPA 和 Hibernate 解决 LazyInitializationException

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

If all you want to return is the ID of the object, I imagine calling getID(), then parse the int/long as a String value at the moment you want it displayed would work just fine. At least that's how it seems based on the question.

EDIT

How to solve the LazyInitializationException using JPA and Hibernate

After viewing the comment and doing some searching I believe this may be most beneficial to your scenario.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文