您的位置:首页 > 其它

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

2019-07-02 16:35 260 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/ZuiChuDeQiDian/article/details/95681970

撸了今年阿里、网易和美团的面试,我有一个重要发现.......>>>

前言:沉浸在代码中,没有跳出来看问题就容易钻牛角尖。还是遇见的问题太少。遇见的问题越多,知道的就会越多。

 

两个不同的实体类深拷贝,然后把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 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是否是新增还是更新。

 

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的不对,哈哈。

 

博客地址:https://my.oschina.net/wangnian

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐