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的。
推荐阅读
- Activiti(一)SpringBoot2集成Activiti6
- SpringBoot调用公共模块的自定义注解失效的解决
- 解决SpringBoot引用别的模块无法注入的问题
- 2018-07-09|2018-07-09 Spring 的DBCP,c3p0
- 数据库总结语句
- spring|spring boot项目启动websocket
- Spring|Spring Boot 整合 Activiti6.0.0
- vue组件中为何data必须是一个函数()
- Spring集成|Spring集成 Mina
- springboot使用redis缓存