springboot 中 @DynamicUpdate 注解无效解决方案
遇到的问题
项目中使用 jpa,以前没用过,所以踩坑在所难免。
在使用过程中,要更新一条记录的某个字段,更新成功以后,发现整条记录只剩下我更新的那个字段,其他的全部为空了。
瞬间明白,这种更新是全覆盖,针对每个字段 update,实体类没赋值的字段,也直接将空值 set 过去了。
寻求解决方案
正在庆幸这么容易就解决,突然发现并没有这么简单。
群众的力量是无穷大的,我立刻就明白这个注解为什么无效,原来是搞错了它的用途。
一孔解决方案
如刚才无数个箭头指向的评论所说,用findOne查出原值,然后赋值想要修改的新的字段值。
思路很简单,这里主要贴一下对象复制的代码。将数据库中查出的对象称为target,包含要修改的字段的对象称为source,当然,最后我们save的是修改之后的target
BeanCopyUtil:
import ch . qos . logback . core . joran . util . beans . BeanUtil ; import org . springframework . beans . BeanUtils ; import org . springframework . beans . BeanWrapper ; import org . springframework . beans . BeanWrapperImpl ; import java . util . HashSet ; import java . util . Set ; /** * created by xxx 2018/7/21 */ public class BeanCopyUtil { //source中的非空属性复制到target中 public static < T > void beanCopy ( T source , T target ) { BeanUtils . copyProperties ( source , target , getNullPropertyNames ( source )); } //source中的非空属性复制到target中,但是忽略指定的属性,也就是说有些属性是不可修改的(个人业务需要) public static < T > void beanCopyWithIngore ( T source , T target , String ... ignoreProperties ) { String [] pns = getNullAndIgnorePropertyNames ( source , ignoreProperties ); BeanUtils . copyProperties ( source , target , pns ); } public static String [] getNullAndIgnorePropertyNames ( Object source , String ... ignoreProperties ) { Set < String > emptyNames = getNullPropertyNameSet ( source ); for ( String s : ignoreProperties ) { emptyNames . add ( s ); } String [] result = new String [ emptyNames . size ()]; return emptyNames . toArray ( result ); } public static String [] getNullPropertyNames ( Object source ) { Set < String > emptyNames = getNullPropertyNameSet ( source ); String [] result = new String [ emptyNames . size ()]; return emptyNames . toArray ( result ); } public static Set < String > getNullPropertyNameSet ( Object source ) { final BeanWrapper src = new BeanWrapperImpl ( source ); java . beans . PropertyDescriptor [] pds = src . getPropertyDescriptors (); Set < String > emptyNames = new HashSet <>(); for ( java . beans . PropertyDescriptor pd : pds ) { Object srcValue = src . getPropertyValue ( pd . getName ()); if ( srcValue == null ) emptyNames . add ( pd . getName ()); } return emptyNames ; } }有了这个方法,在修改的时候就比较方便了,我的做法是在实体类中加一个方法:
//这里我设置【任务编号】和【创建人】不可修改 public void copy ( Task task ) { BeanCopyUtil . beanCopyWithIngore ( task , this , "taskNum" , "createPerson" ); }然后在service中update方法中调用:
@Transactional public Task updateTask ( Task task ) { try { if ( task . getId () == null ) { return null ; } Task saveTask = taskRepository . findOne ( task . getId ()); saveTask . copy ( task ); return taskRepository . saveAndFlush ( task ); } catch ( Exception e ) { throw new CustomException ( SERVER_ERROR , e ); } }总结
使用 springboot 时会遇到非常非常多的注解,这确实为开发省去了大量的时间,和很多没有意义的体力劳动。但是在使用注解的时候,一定要弄清楚用途和用法 ,不然明明是用错了,你还会觉得莫名其妙。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。
原文链接:https://blog.csdn.net/m0_37659871/article/details/81143199
查看更多关于解决springboot中@DynamicUpdate注解无效的问题的详细内容...
声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://www.haodehen.cn/did214520