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的动态更新记录

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐