Java/Hibernate:如何检测字段是否是延迟加载的代理而不是实际数据?

Java/Hibernate:如何检测字段是否是延迟加载的代理而不是实际数据?,java,hibernate,lazy-loading,dto,Java,Hibernate,Lazy Loading,Dto,我正在将我的实体转换为DTO,我想为所有字段设置NULL作为DTO值,这些字段是延迟加载且未初始化的(因为我不想一直传输所有数据) 我试过: if (!(entity.getNationality() instanceof HibernateProxy)) this.setNationalityFromEntity(entity.getNationality()); 但这似乎没有帮助。 欢迎提出任何建议 谢谢大家! 无论是否初始化,该类始终是一个代理,因此,如果只检查代理实例,每次都将

我正在将我的实体转换为DTO,我想为所有字段设置NULL作为DTO值,这些字段是延迟加载且未初始化的(因为我不想一直传输所有数据)

我试过:

if (!(entity.getNationality() instanceof HibernateProxy))
    this.setNationalityFromEntity(entity.getNationality());
但这似乎没有帮助。 欢迎提出任何建议


谢谢大家!

无论是否初始化,该类始终是一个代理,因此,如果只检查代理实例,每次都将排除它。延迟加载不会导致实体上的代理引用被替换为对新对象的引用,它只是填充字段

要知道它是否真的初始化了,你需要问它

if (HibernateProxy.class.isInstance(entity.getNationality())) {
  HibernateProxy proxy = HibernateProxy.class.cast(entity.getNationality());
  if (!proxy.getHibernateLazyInitializer().isUninitialized()) {
    this.setNationalityFromEntity(entity.getNationality());
  }
}

我们在实体中执行此操作的方式是使用布尔方法,这些方法以不会触发延迟加载的方式执行检查。例如,如果我们的实体有一个名为“associatedSomething”的关联实体,那么检查该关联实体是否已延迟加载的方法是:

    public boolean isAssociatedSomethingLoaded() {
        if (associatedSomething instanceof HibernateProxy) {
            if (((HibernateProxy)associatedSomething).getHibernateLazyInitializer().isUninitialized()) {
                return false;
            }
        }
        return (getAssociatedSomething() != null);
    }

注意:在检查中不要使用
getAssociatedSomething()
,这很重要,因为这样可以确保关联实体在检查过程中不会被延迟加载。

我认为,仅仅是能够为用例不可用的某些状态调用getter的可能性是有问题的,但那是另一回事。我建议您实施适当的DTO方法,以避免意外错误

我就是为这个用例创建的。实际上,您将JPA实体的DTO定义为接口,并将其应用于查询。它支持映射嵌套的DTO、集合等,基本上是您所期望的一切,而且最重要的是,它将提高您的查询性能,因为它将生成只获取DTO实际需要的数据的查询

您的示例的实体视图可能如下所示

@EntityView(Person.class)
interface PersonDto {
  String getNationality();
}
List<PersonDto> dtos = entityViewManager.applySetting(
  EntityViewSetting.create(PersonDto.class),
  criteriaBuilderFactory.create(em, Person.class)
).getResultList();
查询可能是这样的

@EntityView(Person.class)
interface PersonDto {
  String getNationality();
}
List<PersonDto> dtos = entityViewManager.applySetting(
  EntityViewSetting.create(PersonDto.class),
  criteriaBuilderFactory.create(em, Person.class)
).getResultList();
List dtos=entityViewManager.applySetting(
EntityViewSetting.create(PersonDto.class),
criteriaBuilderFactory.create(em,Person.class)
).getResultList();

这基本上就是
Hibernate.i初始化(…)
所做的,但范围更广。但是,是的,它为我指明了正确的方向,通过进一步研究懒惰实例,我发现,实体必须不在打开的会话中才能正确地表示初始化状态。我找到的最简单的解决方案是调用
Session.execute(..)
,然后,
Hibernate.isInitialized()
按预期工作。