使用JPA / JPQL是否可以通过其OneToMany关联手动加载和实体?

时间:2019-03-29 12:31:10

标签: spring-boot jpa spring-data-jpa jpql

假设我有2个实体,ParentChild,其中父实体包含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时剥离不必要的部分,所以不希望使用它。

谢谢!

0 个答案:

没有答案