JPA加载多个惰性集合

时间:2018-06-12 13:13:26

标签: java hibernate spring-boot jpa

我有以下实体:

@Entity
public class ProjectEntity implements Project {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne(targetEntity =  FlowEntity.class)
    private Flow flow;
}

@Entity
public class FlowEntity implements Flow {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @OneToMany(targetEntity = StepEntity.class, fetch = FetchType.EAGER)
    private List<Step> steps;
}

@Entity
public class StepEntity implements Step {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToMany(targetEntity = ResourceEntity.class, fetch = FetchType.LAZY)
    private List<Resource> resources;

    @OneToMany(targetEntity = StepRuleEntity.class, fetch = FetchType.LAZY)
    private List<StepRule> rules;

    @ManyToMany(targetEntity = ResourceTypeDataEntity.class, fetch = FetchType.LAZY)
    private List<ResourceTypeData> resourceTypeData;
}

现在当我检索我的项目时,我希望所有内容都已加载。我不能让所有东西都渴望加载,因为它会让一切都变慢。但是对于这个功能,我现在真的需要项目中的所有东西。

我在网上看到你需要在每个集合上调用.size()方法,然后jpa将加载集合但它不起作用。另外我觉得很奇怪我需要在流程的每一步中在我的dao中执行for循环来加载下一个延迟加载的集合。

我的方法使用@Transactional进行注释以获取项目,它是默认的JpaRepostitory

你是如何正确地做到这一点的?

2 个答案:

答案 0 :(得分:0)

正如评论中所述,您可以在查询中使用fetch关键字来执行此操作:

@Query("select p from Project p " + 
    "left join fetch p.flow f " + 
    "left join fetch f.steps s " +
    "left join fetch s.resources " + 
    "left join fetch s.rules " +
    "left join fetch s.resourceTypeData " +
    "where p.id = ?1")
Project findByIdEager(Long id);

如果您希望立即获取所有集合,或者您希望保持集合延迟加载,则允许您使用findByIdEager(..)或者任何默认方法(例如findById(..))。

答案 1 :(得分:0)

理想情况下,@ OneToMany默认情况下必须具有延迟加载的关联。因此,在类 FlowEntity 中,必须懒惰地获取步骤。此外,如答案所示,您可以使用JPQL Join FETCH来急切加载所需的关联。