spring jpa投影嵌套bean

时间:2016-09-10 07:48:05

标签: spring hibernate jpa spring-data-jpa

是否可以使用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建议一个解决方案 提前谢谢

2 个答案:

答案 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());
  }
}

此解决方案有两个缺点:

  1. 强迫你有双向关系地址←→人
  2. 返回List
  3. 另一种解决方案(以及那种首选的JPA方式)就是像这样创建DTO:

    SELECT NEW package.MyPersonDTO(p.name, p.addressList) FROM Person p WHERE …
    

    执行JPQL查询如下:

    List<MyPersonDTO>

    在这种情况下,返回类型将为@Query

    当然,您可以在{{1}}注释中使用任何此解决方案,它应该可以正常工作。