【问题标题】:Hibernate query: new DTO clause not working休眠查询:新的 DTO 子句不起作用
【发布时间】:2012-07-23 14:45:37
【问题描述】:

用户实体

class User{
int id;
@OneToMany
Set<Role> roles;
}

:用户类还有很多我没有写的细节。

DTO

class DTO{
int id;
Set<Role> roles;
DTO(int id, Set<Role> roles){
  this.id = id;
  this.roles= roles;
 }
}

查询

hibernateTemplate.find("select new DTO(u.id, r ) from "+User.class.getName()+ " u inner join u.roles as r");

问题:抛出未找到的有效构造函数。

通过以下构造函数修改,上述查询可以工作:

DTO(int id, Role role){
      this.id = id;
     }

问题:但现在它为同一用户提供了多个 DTO 记录,等于该用户拥有的角色数量。请帮忙。

【问题讨论】:

    标签: java hibernate dto


    【解决方案1】:

    由于您需要多行来创建单个 DTO 实例,因此您不能在查询中使用 new 运算符。相反,您必须自己创建 DTO。应该这样做:

    Map<Long, DTO> dtosById = new LinkedHashMap<Long, DTO>();
    List<Object[]> rows = hibernateTemplate.find("select u.id, r from User u inner join u.roles as r");
    for (Object[] row : rows) {
        Long id = (Long) row[0];
        Role role = (Role) row[1];
        DTO dto = dtosById.get(id);
        if (dto == null) {
            dto = new DTO(id);
            dtosById.put(id, dto);
        }
        dto.addRole(role);
    }
    List<DTO> dtos = new ArrayList<DTO>(dtosById.values());
    

    【讨论】:

    • 这行得通。但我认为hibernate是为了让生活更轻松。 Hibernate 通过向开发人员隐藏关系行为而无法暴露 OO 层。它在每个地方都漏水和漏水。我只能通过查看关系行为来理解这一点——数据库查询是如何工作的:select u.id, r.name from user u, roles r where r.user_id = u.id;这是休眠返回的结果。
    • 对 JDBC 做同样的事情,您会发现 Hibernate 确实让生活变得更轻松。它泄漏了,恕我直言,这是一件好事,因为如果您忘记了 Hibernate 背后有一个关系数据库和 SQL 查询,您将犯下巨大的错误,并且性能将非常糟糕。恕我直言,在不了解幕后发生的事情的情况下使用 Hibernate,只会导致性能灾难。
    • 但是,由于休眠对我来说很容易,它给我带来的痛苦也是一样的。
    【解决方案2】:

    如果您想让事情变得更简单,您会喜欢我为该用例创建的Blaze-Persistence Entity-Views。您基本上将 JPA 实体的 DTO 定义为接口并将它们应用于查询。它支持映射嵌套 DTO、集合等,基本上是您所期望的一切,最重要的是,它会提高您的查询性能,因为它会生成查询,只获取 DTO 实际需要的数据。

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

    @EntityView(User.class)
    interface UserDto {
      @IdMapping Integer getId();
      List<RoleDto> getRoles();
    }
    @EntityView(Role.class)
    interface RoleDto {
      @IdMapping Integer getId();
      String getName();
    }
    

    查询可能如下所示

    List<UserDto> dtos = entityViewManager.applySetting(
      EntityViewSetting.create(UserDto.class),
      criteriaBuilderFactory.create(em, User.class)
    ).getResultList();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-11-18
      • 2013-08-03
      • 1970-01-01
      • 2017-06-22
      • 2015-10-01
      • 1970-01-01
      • 2020-06-20
      • 2018-03-20
      相关资源
      最近更新 更多