spring-data-jpa如何在特定的时候获取lazy加载的数据

发布于 2022-09-05 09:38:39 字数 1244 浏览 11 评论 0

比如说我有两个实体EntityA, EntityB,是多对多关系,并且互相指定默认使用Lazy加载

@Entity
public class EntityA implements Serializable {
    ...
    @ManyToMany(fetch = FetchType.LAZY)
    private List<EntityB> entityBList = new ArrayList<>();
    ...
}

@Entity
public class EntityB implements Serializable {
    ...
    @ManyToMany(mappedBy = "entityBList", fetch= FetchType.LAZY)
    private List<EntityA> entityAList = new ArrayList<>();
    ...
}

在做单元测试的时候,如果通过A获取B的List,会抛出LazyInitializationException

@Test
public void test() throws Exception {
    EntityA a = dao.findOne(id);
    List<EntityB> bList = a.getEntityBList();
    bList.size();  // 这里抛出异常
}

如果在@Test下加上@Transactional倒是可以
但是如果把find方法提出来作为一个新方法调用,则又不行了。。。

@Test
public void test() throws Exception {
    this.getAwithLazyData();
}

@Transactional
public void getAwithLazyData(id) {
    EntityA a = dao.findOne(id);
    List<EntityB> bList = a.getEntityBList();
    bList.size();  // 这里仍然抛出异常
}

当然,如果将fetch= FetchType.LAZY改为fetch= FetchType.EAGER是不会抛异常
不过每次查询就都会带出关联数据了。。。
但我只想在特定的时候带出关联数据,请问应该怎么处理。。。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

草莓酥 2022-09-12 09:38:39

感谢 @Oracle_Ming 的回复。
在找了一些资料之后,发现了一个解决方法,换了一个思考方向
该方法在spring-boot 1.5.6中测试通过

使用@NamedEntityGraph相关注解

Entity上:

@Entity
@NamedEntityGraph(name = "EntityA.lazy", attributeNodes = {@NamedAttributeNode("entityBList")})
public class EntityA implements Serializable {
    ...
    @ManyToMany(fetch = FetchType.LAZY)
    private List<EntityB> entityBList = new ArrayList<>();
    ...
}

对应的Dao上:

@Repository
public interface EntityADao extends SimpleJpaRepository<EntityA, Long> {
    @EntityGraph(attributePaths = { "entityBList" })
    EntityA findWithEntityBById(Long id);
}

这样,如果调用的是原本的findOne方法,则查询结果中的entityBList为lazy数据,无法取出。
如果调用findWithEntityBById方法,则查询结果中已经带出了entityBList,可以直接使用。

不知道有没有更好的方案。

乜一 2022-09-12 09:38:39

我觉得是session过期的原因,你试试不用JPA findOne 查询,改用手写hql,session.query() 试试看。

当爱已成负担 2022-09-12 09:38:39

你可以在@Query的 sql语句中使用 join fetch,比如:

public interface PersonRepository extends JpaRepository<Person, Long> {

    @Query("SELECT p FROM Person p JOIN FETCH p.roles WHERE p.id = (:id)")
    public Person findByIdAndFetchRolesEagerly(@Param("id") Long id);

}

参考:
https://stackoverflow.com/que...

https://www.thoughts-on-java....

也可以看看这个视频,需要科学上网:

https://www.youtube.com/watch...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文