千家信息网

如何解决JPA实体类有Id保存也会新增一条新的数据问题

发表于:2024-10-04 作者:千家信息网编辑
千家信息网最后更新 2024年10月04日,本篇内容介绍了"如何解决JPA实体类有Id保存也会新增一条新的数据问题"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读
千家信息网最后更新 2024年10月04日如何解决JPA实体类有Id保存也会新增一条新的数据问题

本篇内容介绍了"如何解决JPA实体类有Id保存也会新增一条新的数据问题"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

两个不同的实体类深拷贝,然后把id赋值回去更新,会出现一条新数据。

A updateA = DTOMapper.MAPPER.po2po(bAudit);updateA.setId(1)sheetRepository.save(updateA);

1.save方法源码

    /*         * (non-Javadoc)         * @see org.springframework.data.repository.CrudRepository#save(java.lang.Object)         */        @Transactional        public  S save(S entity) {                if (entityInformation.isNew(entity)) {                        em.persist(entity);                        return entity;                } else {                        return em.merge(entity);                }        }

在这里说一下,save上spring就已经加了 @Transactional 开启事务的注解。用spring来管理事务就必须开启事务,不然保存不了,因为SET AUTOCOMMIT=0了。

save方法的第一句代码就是判断entity是否是新增还是更新。

2.看isNew实现

第一个是AbstractPersistable提供的,也是我们熟知的 ,根据id是否为空来判断是否是更新

/**         * Must be {@link Transient} in order to ensure that no JPA provider complains because of a missing setter.         *         * @see org.springframework.data.domain.Persistable#isNew()         */        @Transient // DATAJPA-622        public boolean isNew() {                return null == getId();        }

第二个是 JpaMetamodelEntityInformation提供的

   /*         * (non-Javadoc)         * @see org.springframework.data.repository.core.support.AbstractEntityInformation#isNew(java.lang.Object)         */        @Override        public boolean isNew(T entity) {                if (!versionAttribute.isPresent()                                || versionAttribute.map(Attribute::getJavaType).map(Class::isPrimitive).orElse(false)) {                        return super.isNew(entity);                }                BeanWrapper wrapper = new DirectFieldAccessFallbackBeanWrapper(entity);                return versionAttribute.map(it -> wrapper.getPropertyValue(it.getName()) == null).orElse(true);        }

这个是是根据version版本号来判断是否是更新,问题就出在这里,我们如果更新,必须更新实体的jpaVersion和数据库里的Version一致,不然就是新增操作。

总结:我一直在各种打印 id有木有赋值进去,刚开始是从对象里get出来的,后来又赋值给一个变量,然后怀疑jpa是不是直接拿自己的属性,而不是拿public方法(id是父类继承下来的),反正折腾了好久。

其实回想一下很简单,但是jpa没有给我报错,我觉得是jpa的不对,哈哈。

"如何解决JPA实体类有Id保存也会新增一条新的数据问题"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

0