JPA的新增与修改

遇到的问题

​ 通常情况下,我们在执行新增和修改操作的时候都是依据向后台传入的值是否有id值来进行判断。但是现在使用JPA的时候会发现即使我们进行修改的时候向后台传了id值,也会在数据库中新增一条记录,而不是修改。这主要是因为JPA在底层判断新增和修改的时候是依据version字段来进行判断,而我们在传入的数据中没有version字段,所以一直执行新增操作。

源码分析

​ JPA无论是在执行增加方法还是修改方法,调用的都是save这个方法,因此这就需要在save方法体中来判断何时新增,何时修改。下面我们通过调试程序看一下JPA底层的save方法如何实现。

1、进入SimpleJpaRepository方法中的save方法。

在这里插入图片描述

2、save方法源码

​ 通过查看save方法源码可以看出,其在第一句的时候判断entity是否是一个新的试题,如果是新的进行持久化存储,如果不是则进行合并原数据。下面我们主要看isNew方法的实现。

@Transactional
public <S extends T> S save(S entity) {

    if (entityInformation.isNew(entity)) {
        em.persist(entity);
        return entity;
    } else {
        return em.merge(entity);
    }
}

3、找到isNew方法

​ 我们进入到JpaMetamodelEntityInformation的isNew方法中。
在这里插入图片描述
类继承结构图
在这里插入图片描述

4、isNew方法源码

​ 通过查看源码可以发现,这个方法主要是根据version的版本号来判断是否更新数据,主要问题就出现在这里,如果我们在更新数据的时候必须要更新实体类中的version字段,同时在前端向后台传送数据的时候需要带上version字段,如果没有就是新增操作。具体实现为,该方法首先判断是否有version属性存在,之后获取到实例的包装bean,通过包装bean来判断实体内的version属性值是否为NULL。

@Override
public boolean isNew(T entity) {
	//判断是否有version属性存在
    if (!versionAttribute.isPresent()
        || versionAttribute.map(Attribute::getJavaType).map(Class::isPrimitive).orElse(false)) {
        return super.isNew(entity);
    }
	//获取到实例的包装bean
    BeanWrapper wrapper = new DirectFieldAccessFallbackBeanWrapper(entity);
	//通过包装bean来判断实体内的version属性值是否为NULL
    return versionAttribute.map(it -> wrapper.getPropertyValue(it.getName()) == null).orElse(true);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Whisper~~~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值