解決springboot中@DynamicUpdate注解無(wú)效的問(wèn)題
springboot 中 @DynamicUpdate 注解無(wú)效解決方案
遇到的問(wèn)題
項(xiàng)目中使用 jpa,以前沒(méi)用過(guò),所以踩坑在所難免。
在使用過(guò)程中,要更新一條記錄的某個(gè)字段,更新成功以后,發(fā)現(xiàn)整條記錄只剩下我更新的那個(gè)字段,其他的全部為空了。
瞬間明白,這種更新是全覆蓋,針對(duì)每個(gè)字段 update,實(shí)體類(lèi)沒(méi)賦值的字段,也直接將空值 set 過(guò)去了。
尋求解決方案
正在慶幸這么容易就解決,突然發(fā)現(xiàn)并沒(méi)有這么簡(jiǎn)單。
群眾的力量是無(wú)窮大的,我立刻就明白這個(gè)注解為什么無(wú)效,原來(lái)是搞錯(cuò)了它的用途。
一孔解決方案
如剛才無(wú)數(shù)個(gè)箭頭指向的評(píng)論所說(shuō),用findOne查出原值,然后賦值想要修改的新的字段值。
思路很簡(jiǎn)單,這里主要貼一下對(duì)象復(fù)制的代碼。將數(shù)據(jù)庫(kù)中查出的對(duì)象稱(chēng)為target,包含要修改的字段的對(duì)象稱(chēng)為source,當(dāng)然,最后我們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中的非空屬性復(fù)制到target中 public static <T> void beanCopy(T source, T target) { BeanUtils.copyProperties(source, target, getNullPropertyNames(source)); } //source中的非空屬性復(fù)制到target中,但是忽略指定的屬性,也就是說(shuō)有些屬性是不可修改的(個(gè)人業(yè)務(wù)需要) 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; } }
有了這個(gè)方法,在修改的時(shí)候就比較方便了,我的做法是在實(shí)體類(lèi)中加一個(gè)方法:
//這里我設(shè)置【任務(wù)編號(hào)】和【創(chuàng)建人】不可修改 public void copy(Task task) { BeanCopyUtil.beanCopyWithIngore(task, this, "taskNum", "createPerson"); }
然后在service中update方法中調(diào)用:
@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); } }
總結(jié)
使用 springboot 時(shí)會(huì)遇到非常非常多的注解,這確實(shí)為開(kāi)發(fā)省去了大量的時(shí)間,和很多沒(méi)有意義的體力勞動(dòng)。但是在使用注解的時(shí)候,一定要弄清楚用途和用法 ,不然明明是用錯(cuò)了,你還會(huì)覺(jué)得莫名其妙。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- springboot?html調(diào)用js無(wú)效400問(wèn)題及解決
- SpringBoot2.x中management.security.enabled=false無(wú)效的解決
- Springboot2 session設(shè)置超時(shí)時(shí)間無(wú)效的解決
- springboot2整合redis使用lettuce連接池的方法(解決lettuce連接池?zé)o效問(wèn)題)
- springboot logback調(diào)整mybatis日志級(jí)別無(wú)效的解決
- 完美解決springboot項(xiàng)目出現(xiàn)”java: 錯(cuò)誤: 無(wú)效的源發(fā)行版:17“問(wèn)題(圖文詳解)
相關(guān)文章
Java concurrency線(xiàn)程池之線(xiàn)程池原理(三)_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要為大家詳細(xì)介紹了Java concurrency線(xiàn)程池之線(xiàn)程池原理第三篇,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06IDEA實(shí)現(xiàn)遠(yuǎn)程調(diào)試步驟詳解
這篇文章主要介紹了IDEA實(shí)現(xiàn)遠(yuǎn)程調(diào)試步驟詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09java去除集合中重復(fù)元素示例分享 java去除重復(fù)
這篇文章主要介紹了java去除集合中重復(fù)元素示例,大家參考使用吧2014-01-01關(guān)于Spring自定義XML schema 擴(kuò)展的問(wèn)題(Spring面試高頻題)
今天給大家分享一道spring高頻率面試題關(guān)于Spring自定義XML schema 擴(kuò)展的問(wèn)題,今天以spring整合dubbo的實(shí)例給大家詳細(xì)講解下,感興趣的朋友跟隨小編一起看看吧2021-05-05