jpa 用 save 更新时,如果直接 save(entity)的话,并不会忽略掉 entity 中 null 字段,就导致数据库原有的字段被覆盖。
问题我明白为什么,很难判断开发者需不需要更新 null 值。为啥 jpa 一直不加注解或者配置可以让开发者选择性忽略某些 null 字段?
stackoverflow 上有相关问题,回答都是要先查出来,手动 set 修改字段,然后再 save 一下。这样会有点复杂。entity 要加 @DynamicUpdate 注解(如果不需要更新全部字段的话),字段多的 entity 还需要用 BeanUtils 的工具,并且要手动过滤掉值为 null 的字段。没有别的好点的办法嘛?
ps: 题外话,用了几天感觉 jpa 学习成本比 mybatis 高好多。。不过写注解比写 sql 舒服多了
1
br00k 2020-02-25 19:23:16 +08:00
有这需求你就 save 之前查一下,把不为 null 的值 set 回去不就好了。
|
2
aragakiyuii OP @br00k #1 嗯,现在是这样做的。先把 null 的字段名查出来,再用的 BeanUtils.copyProperties。不过这样感觉被喂了一坨💩一样
|
3
aristotll 2020-02-25 19:47:25 +08:00
这个是 by design 的,和 mybatis 不一样
|
4
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 |
5
hantsy 2020-02-25 19:53:06 +08:00
|
6
yannxia 2020-02-25 19:53:25 +08:00
如何更新成 null 和 null 默认不处理,这两事情总有一个要麻烦点。你选··
|
7
hantsy 2020-02-25 19:58:15 +08:00
>stackoverflow 上有相关问题,回答都是要先查出来,手动 set 修改字段,然后再 save 一下.
这是最基本的策略问题, 和你用 JPA,MyBatis,Spring Data Mongo,还是 JDBC 什么的没有一点关系。 |
8
aragakiyuii OP @hantsy #7 谢谢,我之前用 mybatis 是写<if test="">判断的😂
|
9
RYAN0UP 2020-02-25 20:22:39 +08:00
|
10
br00k 2020-02-25 23:44:45 +08:00
如果你有这种需求,而且要优雅一点。就在 onSaveBefore 或用 AOP 根据 Bean 或者方法上定义的注解统一处理就好了。
|
11
rockyou12 2020-02-25 23:48:40 +08:00
@aragakiyuii 用 mapstruct 这个库,可以生成代码来用一个 bean 更新另一个 bean
@Mapper public interface CarMapper { void updateCarFromDto(CarDto carDto, @MappingTarget Car car); } |
12
caotian 2020-02-26 12:44:46 +08:00
我是这样处理的, 默认更新时忽略 null 值, 如果需要删除值的, 提供单独的方法来更新。
忽略 null 值更新的方法: 提供 http patch 方法, 使用自定义的对象如 payload 来接受并验证, 然后后将 payload 对象序列化为字符串, 过程中忽略掉 null 值, 再用序列化后的字符串, 对原对象进行 json patch, 再将结果 objectMapper 回原对象, 就可以 save 了 |