【问题标题】:Retrieve data from three entities where two of them are in many-to-one relationships with the last one从三个实体中检索数据,其中两个实体与最后一个实体处于多对一关系
【发布时间】:2018-07-22 17:17:15
【问题描述】:

我使用 Spring Boot 作为 REST 后端应用程序。假设 Person 有 Cats 和 Dogs,并且 Cat 和 Dog 都与 Person 存在多对一的关系。这样,Cat 和 Dog 就有了 Person id 作为外键。由于我使用的是 Spring JPA 存储库和多对一关系,因此可以直接获取猫及其人员的列表和狗及其人员的列表。这些列表已转换为 json,我可以使用前端应用程序访问此人的数据。这是我的问题:
我想返回所有人的列表以及每个人的所有猫狗。
我猜 JPA Repository 没有我的请求的默认查询,所以我必须使用自定义查询。但是,我不知道如何制作它。我尝试了以下一种:

@Query("select p, c, d from Person p, Cat c, Dog d where c.person.id = :id and d.person.id = :id and person.id = :id")  
List<Object[]> findAllPersonsWithCatsAndDogs(Integer id);  

这个想法是为每个人运行 for 循环,并使用人的 id 来检索他的猫和狗。结果是对象列表,其中每个对象都有同一个人、他的一只猫和他的一只狗。我不喜欢这样,因为对于所有的人,我都有一份带着他们的猫和狗的人的名单。
如何获得一个所有人的列表以及每个人的所有猫和狗。
谢谢
以下是使之更清晰的映射:

@Entity  
public class Person {  
//there is no mappings because of unidirectional many to one  
}
...  
@Entity  
public class Cat{  
        @ManyToOne  
        @JoinColumn(name = "person_id")
        private Person person;  
}  
...  
@Entity  
public class Dog{  
        @ManyToOne    
        @JoinColumn(name = "person_id")  
        private Person person;  
} 

所以,我有多对一的单向,这意味着 Person 看不到猫和狗。

【问题讨论】:

  • 你能展示你的实体映射java类吗?
  • 是的,我将它们添加到原始问题中。

标签: json spring spring-data-jpa jpql many-to-one


【解决方案1】:

你应该添加人、猫和狗之间的引用。

@Entity  
public class Person {  
  @OneToMany(cascade = CascadeType.PERSIST, mappedBy="person")
  private List<Cat> catList;

  @OneToMany(cascade = CascadeType.PERSIST, mappedBy="person")
  private List<Dog> dogList; 
}

如果你想让所有人都带着他们的猫和狗,你可以做类似的事情

@Query("SELECT p FROM Person P JOIN FETCH p.catList JOIN FETCH p.dogList")
List<Person> findAllPersonsWithCatsAndDogs()

catListdogList 仅被假定为个人列表,因为没有看到您的映射)。

此查询将急切地为每个人获取您的猫和狗列表。然后就可以了

for (Person p : personRepo.findAllPersonsWithCatsAndDogs()) {
  for (Cat c : p.getCastList()) {

  }

  for (Dog d : p.getDogList()) {

  }
}

【讨论】:

  • 我添加了映射。一个人没有猫狗的知识,所以没有p.catList和p.dogList。
  • 您应该添加人猫和狗之间的映射以实现引用完整性并使编写查询更容易。查看我的编辑。
  • 是的,就是这样做的,但我不想使用双向关系,我必须使用多对一的单向关系。这就是为什么它对我来说很棘手。
【解决方案2】:

一般来说,DTO 模式用于包装必要的数据。因此,您可以使用几个对象映射框架,例如 ModelMapper、Modelstruct、Dozer。

如果你为 cat 和 dog Entity 创建了两个仓库,你可以这样做:

CatRepository 中的方法:

List<Cat> findByPersonId(int id);

DogRepository 中的方法:

List<Cat> findByPersonId(int id);

查询人员:

List<Person> persons = personRepository.findAll();
List<PersonDto> personsDto = new ArrayList<>();

foreach(Person p:persons) {
   PersonDto dto = modelmapper.map(p, PersonDto.class);
   p.setCats(catRepo.findByPersonId(p.getId()));
   p.setCats(catRepo.findByPersonId(p.getId()));

   personsDto.add(dto);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-01-13
    • 2020-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    • 1970-01-01
    • 2017-04-06
    相关资源
    最近更新 更多