共计 1179 个字符,预计需要花费 3 分钟才能阅读完成。
先对题目给个具体的解释,其实是个级联保留的问题,我上一段实体代码
@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 的。