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

先对标题给个详细的解释,其实是个级联保存的问题,我上一段实体代码

@Table(name="open_app_user")
@Entity
public class OpenAppUser extends BaseEntity implements UserDetails  {

    /**
     * 所属应用id
     */
    @ApiModelProperty(value="所属应用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的。

你可能感兴趣的:(spring data jpa 关于父实体保存,而子实体存在id会进行多余查询的问题)