是否可以使用Spring JPA进行嵌套集合的投影?
我有以下2个简单实体(解释问题)
@Entity
@Table(name = "person")
public class Person implements Serializable {
private Integer id;
private String name;
@OneToMany
private List<Address> addressList = new ArrayList<>();
}
@Entity
@Table(name = "address")
public class Address implements Serializable {
private Integer id;
private String city;
private String street;
}
是否可以填写具有以下属性的人物投影? {person.name,address.city}
我可能在单词Projection的语义上错了。但问题是我需要实现的。也许用Projection是不可能的,但还有另一种方法来实现最终目标吗?可能是命名实体图吗?
P.S。请为Spring JPA而不是Spring Jpa REST建议一个解决方案 提前谢谢
答案 0 :(得分:3)
你是对,实体图服务于这个目的 - 控制字段加载。
使用命名实体图从代码中动态创建实体图或注释目标实体,然后只使用其名称。
以下是如何修改Person
类以使用命名实体图:
@Entity
@Table(name = "person")
@NamedEntityGraph(name = "persion.name.with.city",
attributeNodes = @NamedAttributeNode(value = "addressList", subgraph = "addresses.city"),
subgraphs = @NamedSubgraph(name = "addresses.city", attributeNodes = @NamedAttributeNode("city")))
public class Person implements Serializable {
private Integer id;
private String name;
@OneToMany
private List<Address> addressList;
}
然后加载你的人时:
EntityGraph graph = em.getEntityGraph("person.name.with.city");
Map hints = new HashMap();
hints.put("javax.persistence.fetchgraph", graph);
return em.find(Person.class, personId, hints);
同样适用于查询,而不仅仅是em.find
方法。
查看this tutorial了解更多详情。
答案 1 :(得分:-1)
我认为这不是Data JPA使用的常见情况。但是你可以用纯JPQL来实现你的目标:
class MyPersonDTO {
private String personName;
private List<String> cities;
public MyPersonDTO(String personName, List<Address> adresses) {
this.personName = personName;
cities = adresses
.stream()
.map(Address::getCity)
.collect(Collectors.toList());
}
}
此解决方案有两个缺点:
另一种解决方案(以及那种首选的JPA方式)就是像这样创建DTO:
SELECT NEW package.MyPersonDTO(p.name, p.addressList) FROM Person p WHERE …
执行JPQL查询如下:
List<MyPersonDTO>
在这种情况下,返回类型将为@Query
。
当然,您可以在{{1}}注释中使用任何此解决方案,它应该可以正常工作。