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

时间:2013-04-08 23:04:10

标签: java hibernate lazy-loading dto

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

我试过了:

if (!(entity.getNationality() instanceof HibernateProxy))
    this.setNationalityFromEntity(entity.getNationality());

但它似乎没有帮助。 欢迎任何建议!

谢谢!

3 个答案:

答案 0 :(得分:4)

我们在实体中这样做是因为我们有布尔方法,它们以不会触发延迟加载的方式进行检查。例如,如果我们的实体有一个名为' associatedSomething'的关联实体,那么检查该关联实体是否已延迟加载的方法将是:

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

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

答案 1 :(得分:2)

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

要了解它是否实际已初始化,您需要询问它!

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

答案 2 :(得分:0)

在我看来,仅能够为某个用例不可用的状态调用getter的可能性是有问题的,但这是另一回事。我建议您采用适当的DTO方法来避免意外错误。

我正是为此用例创建了Blaze-Persistence Entity Views。您实际上将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();