【问题标题】:LazyInitializationException on getId() of a @ManyToOne reference@ManyToOne 引用的 getId() 上的 LazyInitializationException
【发布时间】:2016-01-26 12:16:19
【问题描述】:

当我尝试访问分离实体的惰性 @ManyToOne 引用的 ID 时,我正面临 LazyInitializationException。我不想完全获取引用,而只需要 ID(它应该存在于原始对象中以便以惰性/延迟方式获取引用)。

EntityA ea = dao.find(1) // find is @Transactional, but transaction is closed after method exits
ea.getLazyReference().getId() // here is get exception. lazyReference is a ManyToOne relation and so the foreight key is stored in EntityA side.

解释一下,如何在不实际获取整个 LazyReference 的情况下访问 LazyReference 的 ID(它实际上存在于 EntityA 的初始选择中)?

【问题讨论】:

  • 感谢您的 dup 建议。顺便说一句,您提到的问题可能无法用我自己的问题清楚地回答任何人(尽管回答了我的问题)。答案与 LazyInitializationException 无关,因此人们在搜索此类问题时可能很难找到它。请在此处再次回答 (@Access),建议另一个问题。
  • 不客气。完成,请在下面查看我的答案。

标签: java hibernate lazy-loading many-to-one lazy-initialization


【解决方案1】:

当使用字段访问时,Hibernate 将 getId() 方法与任何其他方法相同,这意味着调用它会触发代理初始化,因此如果在分离的实例上调用它会导致 LazyInitializationException

要仅对 id 属性使用属性访问权限(同时保留所有其他属性的字段访问权限),请为 id 字段指定 AccessType.PROPERTY

@Entity
public class A {
  @Id
  @Access(AccessType.PROPERTY)
  private int id;

  public int getId() {
    return id;
  }

  public void setId(int id) {
    this.id = id;
  }
}

【讨论】:

    【解决方案2】:

    这应该是可能的。我只能获取@ManyToOne LAZY 实体的 ID。

    但为此,我在实体的 getter 上设置了注释,而不是直接在实例变量上设置它们,这会导致 null 值。

    我相信您在实例变量上使用了注释。您可以尝试 getter 注释,看看是否对您有帮助。

    【讨论】:

    • 是的,我实际上是在字段上而不是在 getter 上添加注释。我会尝试使用吸气剂并告诉结果。这是 Hibernate 的错误吗?
    • 我不认为这是一个错误。我记得读过一个解释这种行为的链接。找到链接后,我会尽快发布。
    • @MadhusudanaReddySunnapu 我只是检查了您的建议,它是正确的——如果我们在 getter 上使用注释,则没有任何 LazyInitializationException。我不记得在哪种情况下,但有时,我们的团队在使用 getters 注释方法获取标识符时会遇到此类异常。
    • 我的 ID 字段是字段注释的。我在我的班级(或可能的 ID 字段)上放了一个 @Access(AccessType.FIELD) 并且一切正常。无需在 getter 上添加注释。
    【解决方案3】:

    你会得到一个LazyInitializationException 异常,因为 Hibernate 用代理对象包装了你的持久化对象。代理会为惰性对象的任何 getter 生成异常,即使是 id 当然LazyReference 已经拥有。

    要在没有LazyInitializationException 的情况下获得id,您可以使用this method(您可以参考链接了解其他有趣的实用方法)

    @SuppressWarnings("unchecked")
    public static <T> T getPid(Persistent<?> persistent) {
        if (persistent == null) {
            return null;
        }
    
        if (!(persistent instanceof HibernateProxy) || Hibernate.isInitialized(persistent)) {
            return (T) persistent.getPid();
        }
    
        LazyInitializer initializer = ((HibernateProxy) persistent).getHibernateLazyInitializer();
        return (T) initializer.getIdentifier();
    }
    

    Persistent 是所有持久化对象的基类。对于您的LazyReference,您可以像这样重写代码

    @SuppressWarnings("unchecked")
    public static Long getId(LazyReference persistent) {
        if (persistent == null) {
            return null;
        }
    
        if (!(persistent instanceof HibernateProxy) || Hibernate.isInitialized(persistent)) {
            return persistent.getId();
        }
    
        LazyInitializer initializer = 
            ((HibernateProxy) persistent).getHibernateLazyInitializer();
        return initializer.getIdentifier();
    }  
    

    【讨论】:

      猜你喜欢
      • 2019-01-25
      • 1970-01-01
      • 2013-06-01
      • 2017-02-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多