[英]Hibernate query: new DTO clause not working
用户实体
class User{
int id;
@OneToMany
Set<Role> roles;
}
:User类还有很多其他细节,我还没有写。
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记录,这些记录等于该用户所没有的角色。 请帮忙。
由于您需要多个行来创建单个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());
如果您希望事情变得更轻松,那么您会喜欢我为该用例创建的Blaze-Persistence实体视图 。 您实际上将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();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.