Springboot save()局部更新,@DynamicUpdate生效的条件

springboot 中 @DynamicUpdate 注解无效解决方案

遇到的问题

项目中使用 jpa,以前没用过,所以踩坑在所难免。

在使用过程中,要更新一条记录的某个字段,更新成功以后,发现整条记录只剩下我更新的那个字段,其他的全部为空了。

瞬间明白,这种更新是全覆盖,针对每个字段 update,实体类没赋值的字段,也直接将空值 set 过去了。

首先,用getById()查出原值,然后赋值想要修改的新的字段值(copy克隆赋值)

思路很简单,这里主要贴一下对象复制的代码。将数据库中查出的对象称为target,包含要修改的字段的对象称为source,当然,最后我们save的是修改之后的target。

附上克隆对象的工具:BeanCopyUtil

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 2022/9/29
 */

public class BeanCopyUtil {

    //source中的非空属性复制到target中
    public static  void beanCopy(T source, T target) {
        BeanUtils.copyProperties(source, target, getNullPropertyNames(source));
    }

    //source中的非空属性复制到target中,但是忽略指定的属性,也就是说有些属性是不可修改的(个人业务需要)
    public static  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 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 emptyNames = getNullPropertyNameSet(source);
        String[] result = new String[emptyNames.size()];
        return emptyNames.toArray(result);
    }
    public static Set getNullPropertyNameSet(Object source) {
        final BeanWrapper src = new BeanWrapperImpl(source);
        java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors();
        Set emptyNames = new HashSet<>();
        for (java.beans.PropertyDescriptor pd : pds) {
            Object srcValue = src.getPropertyValue(pd.getName());
            if (srcValue == null) emptyNames.add(pd.getName());
        }
        return emptyNames;
    }
}

有了这个方法,在修改的时候就比较方便了,我的做法是在实体类中加一个方法:

public void copy(Task task) {
        BeanCopyUtil.beanCopyWithIngore(task, this);
}

然后在service或者controller中update方法中调用:

 @Transactional
    public Task updateTask(Task task) {

        try {
            if (task.getId() == null) {
                return null;
            }

            Task saveTask = taskRepository.getById(task.getId());
            saveTask.copy(task);
            return taskRepository.saveAndFlush(saveTask);

        } catch (Exception e) {
            throw new CustomException(SERVER_ERROR, e);
        }

    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个使用Spring Boot实现插入数据的例子: 首先,创建一个实体类,使用`@Data`注解来自动生成Getter、Setter、toString、equals、hashCode等方法: ```java @Data @Entity @Table(name = "users") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @NotBlank private String name; @NotBlank private String email; } ``` 其中,`@Entity`和`@Table`注解用于指定实体类对应的数据库表。 然后,创建一个用于操作数据库的Repository接口: ```java @Repository public interface UserRepository extends JpaRepository<User, Long> { } ``` 接着,创建一个Controller类,用于处理请求并调用Repository接口操作数据库: ```java @RestController @RequestMapping("/users") public class UserController { private final UserRepository userRepository; public UserController(UserRepository userRepository) { this.userRepository = userRepository; } @PostMapping public User createUser(@RequestBody @Valid User user) { return userRepository.save(user); } } ``` 其中,`@PostMapping`注解用于处理POST请求,`@RequestBody`注解用于将请求体中的JSON转换成User对象,`@Valid`注解用于对User对象进行校验,`userRepository.save(user)`方法用于将User对象保存到数据库中。 最后,启动Spring Boot应用程序,使用POST请求发送JSON数据到`/users`接口即可插入数据到数据库中。例如: ```json { "name": "张三", "email": "zhangsan@example.com" } ``` 完整的代码示例可以参考以下链接:https://github.com/spring-guides/gs-accessing-data-rest

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值