关于Spring JPA的一点小总结

业务需求,有联表


实体A

@Entity
class A
{
    @Id
    private Long id;
	
    @OneToMany(fetch=FetchType.EAGER,cascade=CascadeType.ALL)
    @JoinColumn(name = "aId")
    @Fetch(FetchMode.SUBSELECT)
    private Set<B> bs;

    // GET SET toString

}


实体B

@Entity
class B
{
    @Id
    private Long id;

    @Column
    private String data;

    // GET SET toString
}


然后因为业务比较复杂,所以采用的方式是先

save(A) // A.bs=null

save(B)


完成后,findById(A.id)发现A.bs仍为null,于是打开spring的debug日志,发现跟EntityManager有关

猜测:

1,Spring的EntityManager负责DO和事务

2,在findById时,EntityManager发现此实体已经在EM中维护,所以不再查找数据库(所以Hibernate只打印了一条查找A表的语句,而没有打印查找B表的语句,正常情况下,因为设置了

@Fetch(FetchMode.SUBSELECT)
,所以应该在查找A 的时候,也在B中查找,找不到的话,则返回空列表而不是空指针;而实际上,因为EM中维护了A,发现A中的bs为null,则不再查找B表了)

3,另外有测试,如果直接用controller调用findById,则能正常联表查找

4,如果用类似findAll之类的函数查找多条,则也会打印两条Hibernate,但是刚save的那一个仍然包含null的bs

5,讲Spring的debug打开后,发现貌似是一个线程维护一个EM,那么在3中,其实是新开了一个线程,使用了新的EM,所以能正常查找了


解决方法:

cascade=CascadeType.ALL
不用单独save B,直接将B的DO设置到A的bs中,然后jpa自动给同步


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值