当前位置: 首页 > 面试题库 >

Hibernate延迟加载以实现一对一的反向解决方法-这项工作如何进行?

廖永长
2023-03-14
问题内容

我今天遇到问题,在使用按映射的集合时,延迟加载无法正常工作。我发现这篇出色的文章似乎可以解决问题

http://justonjava.blogspot.co.uk/2010/09/lazy-one-to-one-and-one-to-
many.html

我不明白的一件事是使用FieldHandled的解决方法如何工作。谁能帮我理解这一点?有问题的代码如下(从链接中的示例复制):

@Entity
public class Animal implements FieldHandled {
   private Person owner;
   private FieldHandler fieldHandler;

   @OneToOne(fetch = FetchType.LAZY, optional = true, mappedBy = "animal")
   @LazyToOne(LazyToOneOption.NO_PROXY)
   public Person getOwner() {
     if (fieldHandler != null) {
        return (Person) fieldHandler.readObject(this, "owner", owner);
     }
     return owner;
   }

   public void setOwner(Person owner) {
     if (fieldHandler != null) {
       this.owner = fieldHandler.writeObject(this, "owner", this.owner, owner);
       return;
     }
     this.owner = owner;
   }

   public FieldHandler getFieldHandler() {
     return fieldHandler;
   }

   public void setFieldHandler(FieldHandler fieldHandler) {
     this.fieldHandler = fieldHandler;
   }
}

我想念什么?也许我对Hibernate的生命周期了解不够?我乐意进行调查,但任何人都可以给我一些指导。

提前致谢。

编辑

我进行了很多更改,因此许多实体实现了FieldHandled,但随后发现我的某些测试失败了。如果仅使用这些方法集来实现该接口,那么我就抽出了SQL,并得到了一些奇怪的信息,这些SQL以不同的顺序发生了。

   public FieldHandler getFieldHandler() {
     return fieldHandler;
   }

   public void setFieldHandler(FieldHandler fieldHandler) {
     this.fieldHandler = fieldHandler;
   }

这导致测试失败,因为我断言时事情还没有处于正确的状态。这增加了我对该FieldHandler变量的误解。


问题答案:

下面的代码告诉Hibernate使用拦截处理程序代替代理。

@LazyToOne(LazyToOneOption.NO_PROXY)

从javadoc:

返回html" target="_blank">请求引用时加载的真实对象(此选项必须增强字节码,如果未增强该类,则退回到PROXY)

可以看出,在使用字节码之前需要对其进行检测。检测“字节码”后,“持久类得到增强”。

这个想法是要愚弄Hibernate,我们要使用的实体类已经被检测了

编译代码后将调用检测任务。工具实体扩展FieldHandledFieldHandled是“引入增强类的接口”

Hibernate在运行时验证实体,并得出结论,类得到了增强,这就是为什么它使用真实对象而不是代理并且不像往常那样加载相关实体对象的原因。

编辑:

让我们来看看幕后花絮:

  1. AnnotationBinder句柄 NO_PROXY选项

    if ( lazy != null ) {
    toOne.setLazy( !( lazy.value() == LazyToOneOption.FALSE ) );
    toOne.setUnwrapProxy( ( lazy.value() == LazyToOneOption.NO_PROXY ) );
    

    }

  2. 这两个org.hibernate.mapping.ManyToOneorg.hibernate.mapping.OneToOne是的子类org.hibernate.mapping.ToOneToOne#isUnwrapProxy()唯一的用途是#getType

getMappings()。getTypeResolver()。getTypeFactory()。oneToOne(

  1. 这两个ManyToOneTypeOneToOneType是的子类EntityType,只有“的EntityType#unwrapProxy”的用法是在EntityType#resolveIdentifier(Serializable, SessionImplementor)

    boolean isProxyUnwrapEnabled = unwrapProxy &&
        session.getFactory()
                .getEntityPersister( getAssociatedEntityName() )
                .isInstrumented();
    
  2. 这是暂定的呼叫层次结构:AbstractEntityPersister#isInstrumented()-> EntityMetamodel#isInstrumented()-> EntityInstrumentationMetadata#isInstrumented()->等,最后BytecodeProviderImpl.EntityInstrumentationMetadataImpl.EntityInstrumentationMetadataImpl()

     this.isInstrumented = FieldHandled.class.isAssignableFrom( entityClass );
    

这就是为什么需要检测代码(例如使用InstrumentTask)或实现的原因FieldHandled

为了使长话短说你可以看一看EntityType#resolveIdentifier(Serializable, SessionImplementor)。这就是为什么即使第二个对象为空也不会加载的原因。



 类似资料:
  • 本文向大家介绍Mybatis一对一延迟加载实现过程解析,包括了Mybatis一对一延迟加载实现过程解析的使用技巧和注意事项,需要的朋友参考一下 需求:用户和账户一对一关系,查询账户时实现用户的延迟加载 思路:根据id查询,需要延迟加载的一方 1、用户实体类 2、账户实体类 3、用户持久层接口 4、账户持久层接口 5、全局配置文件 6、用户映射配置文件 7、账户映射配置文件 以上就是本文的全部内容,

  • 我面临的问题是一对一的惰性加载在Hibernate中不起作用。我已经解决了,但还是不明白会发生什么。 我的代码(懒惰加载在这里不起作用,当我拉person-address也被提取): 但是:如果我在OneToOne关系中添加,那么惰性加载工作很好! 问题/恳求:请给我解释一下注释如何帮助实现延迟加载。 附注。我看过post1和post2,明白了为什么简单的OneToOne不能偷懒,但我还是不能掌握

  • 问题内容: 当我做 我看到两个查询被解雇了。一个用于获取人员数据,另一个用于人员详细数据。 根据我的理解,应该仅触发1个查询来获取人数据而不是人详细数据,因为我已经提到了延迟加载。为什么personDetail数据与person数据一起获取? 问题答案: Hibernate无法像代理关系中的Sets / Lists一样代理自己的对象,因此延迟加载不起作用。 我认为此链接可能有助于理解您的问题:ht

  • 问题内容: 如果实体A具有与实体B的双向一对一或零对一映射。 映射如下: 和 当我对EntityA进行hql查询(或更确切地说,是命名的hql查询)时,hibernate会急切地用单独的select语句加载EntityA#propertyB。 我的问题是,如果我的hql返回1000个EntityA(所有人都有各自的EntityB),hibernate将执行n + 1个查询(第一个查询是针对Enti

  • 当执行session . create query(" from Author ")时。list();即使关系被标记为optional=false,fetch type = lazy from Author- Hibernate:选择author0_。作者ID为作者I1 0,作者0。电子邮件为email2_0_,author0_。名为name3_0_ from AUTHOR author0_ Hi