0

用户实体

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 记录,等于该用户拥有的角色数量。请帮忙。

4

2 回答 2

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());
于 2012-07-23T14:52:22.273 回答
0

如果你想让事情变得更简单,你会喜欢我为那个用例创建的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();
于 2018-07-19T18:39:09.220 回答