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

比如有两个实体A, B是多对多关系,并且相互指定默认使用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();  // 这里抛出异常
}

当然,解决办法加一个@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是不会抛异常 不过每次查询就都会带出关联数据了。

如何在特定的时候带出关联数据:

        (其实还是session过期了,数据没有取出来)之前调用的findOne方法,则查询结果中的entityBList为lazy数据,无法取出,解决办法就是如果调用findWithEntityBById方法,则查询结果中已经带出了entityBList,可以直接使用。

使用@NamedEntityGraph相关注解

@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);
}

或者也可以直接取出来~

@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);

}
这样也就是把数据先初始化,防止session过期后再去取就报异常了

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值