本篇内容介绍了“如何解决JPA实体类有Id保存也会新增一条新的数据问题”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
两个不同的实体类深拷贝,然后把id赋值回去更新,会出现一条新数据。
A updateA = DTOMapper.MAPPER.po2po(bAudit);
updateA.setId(1)
sheetRepository.save(updateA);
/*
* (non-Javadoc)
* @see org.springframework.data.repository.CrudRepository#save(java.lang.Object)
*/
@Transactional
public <S extends T> 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是否是新增还是更新。
第一个是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保存也会新增一条新的数据问题”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。
原文链接:https://my.oschina.net/wangnian/blog/3068605