spring jpa 更新 null 值的问题

2020-02-25 19:17:54 +08:00
 aragakiyuii

jpa 用 save 更新时,如果直接 save(entity)的话,并不会忽略掉 entity 中 null 字段,就导致数据库原有的字段被覆盖。

问题我明白为什么,很难判断开发者需不需要更新 null 值。为啥 jpa 一直不加注解或者配置可以让开发者选择性忽略某些 null 字段?

stackoverflow 上有相关问题,回答都是要先查出来,手动 set 修改字段,然后再 save 一下。这样会有点复杂。entity 要加 @DynamicUpdate 注解(如果不需要更新全部字段的话),字段多的 entity 还需要用 BeanUtils 的工具,并且要手动过滤掉值为 null 的字段。没有别的好点的办法嘛?

ps: 题外话,用了几天感觉 jpa 学习成本比 mybatis 高好多。。不过写注解比写 sql 舒服多了

5009 次点击
所在节点    Java
12 条回复
br00k
2020-02-25 19:23:16 +08:00
有这需求你就 save 之前查一下,把不为 null 的值 set 回去不就好了。
aragakiyuii
2020-02-25 19:32:33 +08:00
@br00k #1 嗯,现在是这样做的。先把 null 的字段名查出来,再用的 BeanUtils.copyProperties。不过这样感觉被喂了一坨💩一样
aristotll
2020-02-25 19:47:25 +08:00
这个是 by design 的,和 mybatis 不一样
hantsy
2020-02-25 19:51:27 +08:00
跟用什么东西没有关系,

一段伪代码,

1. 首先,
从 Web 取出数据,

var toUpdate=controller.getFromRequestBody

2. 查询数据库已经存在的数据

var saved = repo.findOne(id)

saved.setContent(toUpdate.getContent)

3. 保存(不是必须的,在事务内可以自己同步)
repo.save(saved)

参考
https://github.com/hantsy/spring-reactive-sample/blob/master/boot-data-r2dbc/src/main/java/com/example/demo/PostController.java#L37-L47
hantsy
2020-02-25 19:53:06 +08:00
yannxia
2020-02-25 19:53:25 +08:00
如何更新成 null 和 null 默认不处理,这两事情总有一个要麻烦点。你选··
hantsy
2020-02-25 19:58:15 +08:00
>stackoverflow 上有相关问题,回答都是要先查出来,手动 set 修改字段,然后再 save 一下.
这是最基本的策略问题, 和你用 JPA,MyBatis,Spring Data Mongo,还是 JDBC 什么的没有一点关系。
aragakiyuii
2020-02-25 20:15:58 +08:00
@hantsy #7 谢谢,我之前用 mybatis 是写<if test="">判断的😂
RYAN0UP
2020-02-25 20:22:39 +08:00
br00k
2020-02-25 23:44:45 +08:00
如果你有这种需求,而且要优雅一点。就在 onSaveBefore 或用 AOP 根据 Bean 或者方法上定义的注解统一处理就好了。
rockyou12
2020-02-25 23:48:40 +08:00
@aragakiyuii 用 mapstruct 这个库,可以生成代码来用一个 bean 更新另一个 bean

@Mapper
public interface CarMapper {

void updateCarFromDto(CarDto carDto, @MappingTarget Car car);
}
caotian
2020-02-26 12:44:46 +08:00
我是这样处理的, 默认更新时忽略 null 值, 如果需要删除值的, 提供单独的方法来更新。
忽略 null 值更新的方法: 提供 http patch 方法, 使用自定义的对象如 payload 来接受并验证, 然后后将 payload 对象序列化为字符串, 过程中忽略掉 null 值, 再用序列化后的字符串, 对原对象进行 json patch, 再将结果 objectMapper 回原对象, 就可以 save 了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/647501

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX