JPA保存关联多对多只读实体时仅提供关联ID是否可完成映射?
JPA多对多关联只读配置实体的保存问题解答
核心结论
两种操作都可以实现正确的关联映射,你可以根据业务场景选择更适合的方案,不需要强制查询完整的B实体。
方案1:仅用B的ID完成关联(性能最优,推荐)
- 直接通过
EntityManager.getReference(B.class, bId)或者Spring Data JPA的getReferenceById(bId)(2.7版本前方法名为getById)获取B的代理对象,这个操作不会触发实际的数据库查询 - 将生成的B代理对象直接放入A的关联集合中,保存A即可完成关联映射
- 优势:完全不会对B的只读配置表产生查询请求,关联的B数量较多时性能优势非常明显
- 注意事项:不要调用B代理对象除
getId()之外的其他字段getter方法,否则会触发代理初始化,执行实际的B表查询
方案2:先查询完整B实体再关联
- 调用
findById()查询得到完整的B持久化实体,再放入A的关联集合中保存,完全可以正常映射 - 优势:如果保存A前需要用B的其他字段做业务校验,该方案更直接
- 劣势:会产生额外的B表查询开销,关联B数量较多时性能不如方案1
必做配置提醒
因为B是只读配置表,禁止插入更新,你需要确保A的多对多关联注解不要配置B相关的级联增改操作,参考配置如下:
// 仅配置关联关系,不设置任何级联增改操作 @ManyToMany(cascade = {}) @JoinTable( name = "a_b_relation", joinColumns = @JoinColumn(name = "a_id"), inverseJoinColumns = @JoinColumn(name = "b_id") ) private List<B> bList;
不要添加
CascadeType.PERSIST、CascadeType.MERGE这类级联规则,否则保存A的时候JPA会尝试插入或更新B实体,触发只读表操作异常。
内容的提问来源于stack exchange,提问作者DeltaT
相关产品推荐
相关产品推荐

