spring|spring data jpa 关于父实体保存,而子实体存在id会进行多余查询的问题

【spring|spring data jpa 关于父实体保存,而子实体存在id会进行多余查询的问题】先对标题给个详细的解释,其实是个级联保存的问题,我上一段实体代码

@Table(name="open_app_user") @Entity public class OpenAppUser extends BaseEntity implements UserDetails{/** * 所属应用id */ @ApiModelProperty(value="https://www.it610.com/article/所属应用id") @ManyToOne @JoinColumn(name = "app_id") //private Integer appId; private OpenApp openApp; // ...}@Table(name="open_app") @Entity public class OpenApp extends BaseEntity {// ...}

这里有两个实体,一个是父实体OpenAppUser,一个是子实体OpenApp,我遇到的一个问题是,我需要保存OpenAppUser,但是需要一个OpenApp对象,我在前端传了一个id映射到OpenApp里了,但是在保存的时候appUserRepository.save(appUser); 因为openApp是一个瞬态实体,会报找不到app_id异常(这是我app_user表里的app_id字段)。
后来我试了一下在save之前,我先使用appRepository.findById(appId); 把openApp对象通过查询的方式变成了持久化实体,再去save(appUser); 这时候是可以的。
不过看打印的sql日志,这种保存方式,在这之前都要进行查询,这里是依赖了应用,可能还有其他的,比如用户所属部门等等,那样的效率就低了,我想着在我保存的时候,我只需要传其他依赖的id就行了,不需要一个完整的对象,我就开始看hibernate官方文档,发现了entityManager有个getReference(id)方法可以返回一个实体代理,获取这个实体代理的时候并不一定就会查询数据库。
然后我就发现spring data jpa的实现类里JpaRepository的getById(id)就是调用的entityManager.getReference(id),然后把appRepository.findById(appId)改成appRepository.getById(appId),再去看sql打印的时候,这次就没有再查询了,而是直接用的openApp代理实体里的id属性(我也只有这个属性,是通过前端传的)。这个插入效率就高很多了,一下子优化了查询。
spring data jpa 关于存在id保存,不存在id则新增的处理,有个AbstractPersistable类,可以通过设置它来实现,spring里面是通过判断id是不是null来走entityManager.persist还是merg的。

    推荐阅读