解決springboot中@DynamicUpdate注解無效的問題
springboot 中 @DynamicUpdate 注解無效解決方案
遇到的問題
項目中使用 jpa,以前沒用過,所以踩坑在所難免。
在使用過程中,要更新一條記錄的某個字段,更新成功以后,發(fā)現(xiàn)整條記錄只剩下我更新的那個字段,其他的全部為空了。
瞬間明白,這種更新是全覆蓋,針對每個字段 update,實體類沒賦值的字段,也直接將空值 set 過去了。
尋求解決方案

正在慶幸這么容易就解決,突然發(fā)現(xiàn)并沒有這么簡單。

群眾的力量是無窮大的,我立刻就明白這個注解為什么無效,原來是搞錯了它的用途。
一孔解決方案
如剛才無數(shù)個箭頭指向的評論所說,用findOne查出原值,然后賦值想要修改的新的字段值。
思路很簡單,這里主要貼一下對象復(fù)制的代碼。將數(shù)據(jù)庫中查出的對象稱為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中的非空屬性復(fù)制到target中
public static <T> void beanCopy(T source, T target) {
BeanUtils.copyProperties(source, target, getNullPropertyNames(source));
}
//source中的非空屬性復(fù)制到target中,但是忽略指定的屬性,也就是說有些屬性是不可修改的(個人業(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;
}
}
有了這個方法,在修改的時候就比較方便了,我的做法是在實體類中加一個方法:
//這里我設(shè)置【任務(wù)編號】和【創(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 時會遇到非常非常多的注解,這確實為開發(fā)省去了大量的時間,和很多沒有意義的體力勞動。但是在使用注解的時候,一定要弄清楚用途和用法 ,不然明明是用錯了,你還會覺得莫名其妙。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
解決IDEA集成Docker插件后出現(xiàn)日志亂碼的問題
這篇文章主要介紹了解決IDEA集成Docker插件后出現(xiàn)日志亂碼的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-11-11
Java中valueOf和parseInt的區(qū)別詳解
這篇文章主要介紹了Java中valueOf和parseInt的區(qū)別詳解,在編程中,遇到類型轉(zhuǎn)換,好像會經(jīng)常用到 parseInt 和 valueOf,當然這里只拿 Integer 類型進行陳述,其他類型也是雷同的,需要的朋友可以參考下2024-01-01
Spring Boot中使用Actuator的/info端點輸出Git版本信息
這篇文章主要介紹了Spring Boot中使用Actuator的/info端點輸出Git版本信息,需要的朋友可以參考下2017-06-06
深入Spring Boot之ClassLoader的繼承關(guān)系和影響
這篇文章主要介紹了深入Spring Boot之ClassLoader的繼承關(guān)系和影響,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-06-06
MyBatisPlus的autoResultMap生成策略實現(xiàn)
本文主要介紹了MyBatisPlus的autoResultMap生成策略實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習或者工作具有一定的參考學(xué)習價值,需要的朋友們下面隨著小編來一起學(xué)習學(xué)習吧2024-02-02
java 過濾器模式(Filter/Criteria Pattern)詳細介紹
這篇文章主要介紹了java 過濾器模式(Filter/Criteria Pattern)詳細介紹的相關(guān)資料,需要的朋友可以參考下2016-10-10
Java中調(diào)用Python的實現(xiàn)示例
本文主要介紹了Java中調(diào)用Python的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習或者工作具有一定的參考學(xué)習價值,需要的朋友們下面隨著小編來一起學(xué)習學(xué)習吧2023-05-05

