假设我有2个实体,Parent
和Child
,其中父实体包含1..n个子实体:
@Entity
@Data @NoArgsConstructor
public class Parent {
@Id @GeneratedValue
private long id;
private String basic;
private String detail;
@OneToMany(fetch = FetchType.EAGER)
private Set<Child> children = new HashSet<>();
public Parent(String basic, String detail, Set<Child> children) {...}
}
@Entity
@Data @NoArgsConstructor
public class Child {
@Id
@GeneratedValue(strategy = GenerationType.TABLE)
private long id;
private String basic;
private String detail;
public Child(String basic, String detail) {...}
}
我可以使用JpaRepository加载父实体:
public interface ParentRepository extends JpaRepository<Parent, Long> { }
// in Controller or Service
List<Parent> parents = parentRepository.findAll();
我正在尝试使用投影。因此,我想知道是否可以通过查询手动加载父项,以便仅加载所需的数据。在一个完美的世界中,这可能看起来像这样:
// Dtos, the String detail is not required for both Parent and Child
@Value
public class ParentDto {
long id;
String basic;
Collection<Child> children;
public ParentDto(long id, String basic, Collection<ChildDto> children) {...}
}
@Value
public class ChildDto {
long id;
String basic;
public ChildDto(long id, String basic) {...}
}
和
public interface ParentRepository extends JpaRepository<Parent, Long> {
// Projection - *NOT WORKING*, this is what i would like
@Query("select p.id, p.basic, p.children.id, p.children.basic from Parent p")
List<ParentDto> findAllProjected();
}
这显然失败了,因为它将所有父母与他们的孩子一起加入,导致了amount_of_parents * * amount_of_their_children行。 ParentDto需要一个委托人public ParentDto(long id, String basic, ChildDto child) {...}
,所以我每个父母有n个ParentDto,其中n是父母拥有的孩子数。
我是否必须按父ID手动对行进行分组,并将ChildDtos收集在一起?我可以使用子选择解决此问题吗?我知道Jpa通过选择父级并为每个父级执行1选择,以获取其子级来解决此问题(当我使用自动生成的存储库方法时)。我真的希望投影/视图会更容易,因为它们是我和大多数其他应用程序的基本要求。必须始终加载所有数据,仅加载所需的数据-但无需它们的关联,也不必手动为每个实体加载关联。
注意:我确实尝试过InterfaceProjection,但是由于它加载所有数据并仅在将其序列化为json时剥离不必要的部分,所以不希望使用它。
谢谢!