Я использую Java EE 7 с Java 8 и Hibernate (5.0.X) в Wildfly 10.1.0-Final, и мне нужно загрузить результат запроса JPQL в DTO с помощью проекций, но я не могу найти какую-либо документациюо том, как загрузить дочерние DTO коллекции.
Например, если у меня есть следующие сущности для пользователя, роли и привилегии:
@Entity
public class User
{
@Id
private long id;
private String userName;
private String firstName;
private String lastName;
private JobTitle jobTitle;
private Email email;
private boolean isRemote;
@ManyToMany
private Set<Tag> tags;
@ManyToMany
// @JoinColumn definitions...
private Set<Role> roles;
// getters/setters...
}
@Entity
public class Role
{
@Id
private long id;
private String name;
private String description;
@ManyToMany
// @JoinColumn definitions...
private Set<Privilege> privileges;
// getters/setters...
}
@Entity
public class Privilege
{
@Id
private long id;
private String key;
private String name;
private String description;
// getters/setters...
}
И я хочу использовать проекции для загрузкинекоторые запросы приводят к следующим неизменяемым DTO (предположим, что все имеют hashCode и равнозначные, реализованные на основе идентификатора):
public class UserDTO
{
private final long id;
private final String userName;
private final Set<RoleDTO> roles = new HashSet<>();
public UserDTO(long id, String userName, Collection<RoleDTO> roles) // not sure if this is correct for projection..
{
this.id = id;
this.userName = userName;
this.roles.addAll(roles);
}
public Set<Role> getRoles()
{
return Collections.unmodifiableSet(roles);
}
// getters
}
public class RoleDTO
{
private final long id;
private final String name;
private final Set<PrivilegeDTO> privileges = new HashSet<>();
public RoleDTO(long id, String name, Set<PrivilegeDTO> privileges)
{
this.id = id;
this.name = name;
this.privileges.addAll(privileges);
}
public Set<Privilege> getPrivileges()
{
return Collections.unmodifiableSet(privileges);
}
// other getters
}
public class PrivilegeDTO
{
private final long id;
private final String key;
public PrivilegeDTO(long id, String key)
{
this.id = id;
this.key = key;
}
// getters
}
Как будет выглядеть структура запроса JPQL для достижения этой цели?Я почти уверен, что смогу выполнить работу, выполнив объединения, а затем обработав результаты в DTO-объектах, что-то вроде этого (для загрузки 50 новых пользователей по ID):
List<Object[]> results = em.createQuery("SELECT u.id, u.userName, r.id, "
+ "r.name, p.id, p.key FROM User u "
+ "LEFT JOIN u.roles r "
+ "LEFT JOIN r.privileges p "
+ "ORDER BY u.id DESC")
.setMaxResults(50).getResultList();
Map<Long, UserDTO> users = new HashMap<>();
Map<Long, RoleDTO> roles = new HashMap<>();
Map<Long, PrivilegeDTO> privileges = new HashMap<>();
for(Object[] objArray : results)
{
// process these into the DTO objects,
}
реконструкция должна была начаться с объектов PrivilegeDTO, затем с RoleDTO и, наконец, с UserDTO.Это обеспечит неизменность, потому что вам нужны объекты PrivilegeDTO при создании объектов RoleDTO, или вам придется добавить их позже, что означает, что RoleDTO не является неизменным.
Это было бы забавным упражнением в Streams, ноЯ бы предпочел иметь возможность просто построить это из запроса, кажется, что это должно быть быстрее.Это вообще возможно?
Большое спасибо!