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的动态更新记录
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)