JPA实现部分字段动态更新

JPA实现部分字段动态更新

在使用jpa进行操作数据库时,我们经常会遇到更新数据问题。jpa的save方法可以解决这个问题,但这个方法有一个局限,在匹配到相同主键的记录是可以进行更新,但是会将传入参数的值全部更新到数据库中。
例如下面两个对象

数据库:
demo{
     id:1,
     name:one,
     number:123
     info:yes
}
传入参数:
demo2{
     id:1,
     name:two,
     number:null
     info:null
}

在上面这种情况下,你的目的可能只是更新某个值,例如只修改name在数据库的存储值,并不修改其他的值,如下图所示:
在这里插入图片描述

但是jpa的save默认会将demo2的值直接覆盖数据库中demo的值,此时number和info的值也会修改,结果如下图
在这里插入图片描述
为了实现部分更新可以采用在实体类上标注@DynamicUpdate 和配合BeanUtils的方式

代码

实现复制非空属性值的工具类

package com.example.demo.Utils;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;

import java.beans.PropertyDescriptor;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Stream;

public class JpaUtil {
    public static void copyNotNullProperties(Object src,Object target){
        BeanUtils.copyProperties(src,target,getNullPropertyNames(src));
    }

    public static String[] getNullPropertyNames (Object source) {
        final BeanWrapper src = new BeanWrapperImpl(source);
        java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors();

        Set<String> emptyNames = new HashSet<String>();
        for(java.beans.PropertyDescriptor pd : pds) {
            Object srcValue = src.getPropertyValue(pd.getName());
            if (srcValue == null) {
                emptyNames.add(pd.getName());
            }
        }
        String[] result = new String[emptyNames.size()];
        return emptyNames.toArray(result);
    }

}

实体类

package com.example.demo.entities;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.*;
import lombok.experimental.Accessors;
import org.hibernate.annotations.DynamicUpdate;

import javax.persistence.*;
import java.io.Serializable;

/**
 * @author xiaow
 */
@Entity
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Data
@Table(name="apply")
@Accessors(chain = true)
@JsonIgnoreProperties(value = { "hibernateLazyInitializer"})
@DynamicUpdate     //动态更新
public class Apply implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private Integer state;
    private Integer studentid;
    private Integer awardtype;
    private String info;
    private String name;
    private Integer type;
    private Integer teacherid;
   private Integer teacherstate;
}

持久层

public interface ApplyRepos extends JpaRepository<Apply,Integer> {}

事务实现层

   public int updateAll(Apply apply) {
        int a=0;
        if(apply!=null&&apply.getId() != null) {
            Apply apply1 = applyRepos.getOne(apply.getId());
            if (apply1!=null) {
            //将apply中非空的值赋给apply1中,并将apply1重新存储
                JpaUtil.copyNotNullProperties(apply, apply1);   
            }
            a=applyRepos.save(apply1).getId();
        }
        return a;
    }

这样就实现了jpa的动态更新记录

posted @   就很有趣xiaow  阅读(1503)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示