Spring Data JPA сопоставляет собственный результат запроса с не-сущностью POJO
у меня есть метод хранилища данных Spring с собственным запросом
@Query(value = "SELECT g.*, gm.* FROM group g LEFT JOIN group_members gm ON g.group_id = gm.group_id and gm.user_id = :userId WHERE g.group_id = :groupId", nativeQuery = true)
GroupDetails getGroupDetails(@Param("userId") Integer userId, @Param("groupId") Integer groupId);
и я хотел бы сопоставить результат с не-сущностью POJO GroupDetails
.
возможно ли это, и если да, не могли бы вы привести пример ?
5 ответов
предполагая GroupDetails, как в ответе orid, вы пробовали JPA 2.1 @ConstructorResult?
@SqlResultSetMapping(
name="groupDetailsMapping",
classes={
@ConstructorResult(
targetClass=GroupDetails.class,
columns={
@ColumnResult(name="GROUP_ID"),
@ColumnResult(name="USER_ID")
}
)
}
)
@NamedNativeQuery(name="getGroupDetails", query="SELECT g.*, gm.* FROM group g LEFT JOIN group_members gm ON g.group_id = gm.group_id and gm.user_id = :userId WHERE g.group_id = :groupId", resultSetMapping="groupDetailsMapping")
и используйте следующее в интерфейсе репозитория:
GroupDetails getGroupDetails(@Param("userId") Integer userId, @Param("groupId") Integer groupId);
по данным Spring JPA документация, spring сначала попытается найти именованный запрос, соответствующий вашему имени метода, используя @NamedNativeQuery
, @SqlResultSetMapping
и @ConstructorResult
вы должны быть в состоянии достичь, что поведение
Я думаю, что самый простой способ сделать это-использовать так называемые проекции. Он может сопоставлять результаты запросов с интерфейсами. Используя SqlResultSetMapping
является непостоянным и делает ваш код уродливым :).
пример прямо из исходного кода spring data JPA:
public interface UserRepository extends JpaRepository<User, Integer> {
@Query(value = "SELECT firstname, lastname FROM SD_User WHERE id = ?1", nativeQuery = true)
NameOnly findByNativeQuery(Integer id);
public static interface NameOnly {
String getFirstname();
String getLastname();
}
}
вы также можете использовать этот метод для получения списка проекций.
проверьте эту запись spring data JPA docs для получения дополнительной информации о проекциях.
Примечание.:
Не забудьте иметь свой User
объект, определенный как обычный-поля из проектируемого интерфейса должны соответствовать полям в этом объекте. В противном случае отображение полей может быть нарушено (getFirstname()
может возвращать значение фамилии и т. д.).
Если GroupDetails
что-то вроде:
public class GroupDetails {
int groupId;
int userId;
public GroupDetails(int groupId , int userId) {
this.groupId = groupId;
this.userId = userId;
}
// getters setters, etc.
}
следующее должно работать:
@Query(value = "SELECT new GroupDetails(gm.group_id, gm.user_id) FROM group g LEFT JOIN group_members gm ON g.group_id = gm.group_id and gm.user_id = :userId WHERE g.group_id = :groupId")
Вы можете сделать что-то вроде
@NamedQuery(name="IssueDescriptor.findByIssueDescriptorId" ,
query=" select new com.test.live.dto.IssuesDto (idc.id, dep.department, iss.issueName,
cat.issueCategory, idc.issueDescriptor, idc.description)
from Department dep
inner join dep.issues iss
inner join iss.category cat
inner join cat.issueDescriptor idc
where idc.id in(?1)")
и должен быть конструктор типа
public IssuesDto(long id, String department, String issueName, String issueCategory, String issueDescriptor,
String description) {
super();
this.id = id;
this.department = department;
this.issueName = issueName;
this.issueCategory = issueCategory;
this.issueDescriptor = issueDescriptor;
this.description = description;
}
в моем компьютере, я получаю этот код работает.Это немного отличается от ответа Даймона.
@SqlResultSetMapping(
name="groupDetailsMapping",
classes={
@ConstructorResult(
targetClass=GroupDetails.class,
columns={
@ColumnResult(name="GROUP_ID",type=Integer.class),
@ColumnResult(name="USER_ID",type=Integer.class)
}
)
}
)
@NamedNativeQuery(name="User.getGroupDetails", query="SELECT g.*, gm.* FROM group g LEFT JOIN group_members gm ON g.group_id = gm.group_id and gm.user_id = :userId WHERE g.group_id = :groupId", resultSetMapping="groupDetailsMapping")