在JPA中,使用save方法时是这样的:如果我们save的对象指定了主键,那么会根据主键先进行一次查询,如果查询记录不存在则执行insert语句,如果查询记录存在则执行update语句。

业务场景是这样的:当某个用户钱包流水发生变化时,我们会先查询用户钱包是否存在(新注册的用户一开始没有钱包),如果存在则直接更新钱包余额,并添加一条流水,如果用户钱包不存在,则新生成钱包,再更新钱包余额,最后添加流水。

当同一个用户同时产生多条流水时,现在的流程则可能出现问题。

// 查询用户钱包是否存在
User u = select(userId);
if(u == null){
	// 不存在则生成钱包,初始化钱包余额为0
	jpa.save(u);
// 添加流水
addFlow(u);
// 更新钱包余额
update(u);

问题就发生在当第一个线程save成功后,第二个线程再执行时,save就会变成update,并且会覆盖第一个线程所执行的操作。

只要让自定义save方法,就是insert操作就可以了,当第2个线程save时,会报主键冲突,然后第2个线程再重试一次,再次查询钱包是否存在时,就可以查询到了,然后就不用再生成钱包了,直接更新余额即可(更新余额幂等性)。

前言在JPA中,使用save方法时是这样的:如果我们save的对象指定了主键,那么会根据主键先进行一次查询,如果查询记录不存在则执行insert语句,如果查询记录存在则执行update语句。问题现象业务场景是这样的:当某个用户钱包流水发生变化时,我们会先查询用户钱包是否存在(新注册的用户一开始没有钱包),如果存在则直接更新钱包余额,并添加一条流水,如果用户钱包不存在,则新生成钱包,再更新钱包余额,最后添加流水。当同一个用户同时产生多条流水时,现在的流程则可能出现问题。伪代码// 查询用户钱包是否
刚开始使用JPA 的小伙伴们,可能有些困惑: 如下源码所示,JPA的CrudRepository只有save 方法,没有update和create方法。我怎样告诉JPA我是要更新(update)而不是插入(create)? @NoRepositoryBean public interface CrudRepository<T, ID> extends Repository<T, ...
问题:修改更新数据库部分字段,用save()方法进行update操作,未修改字段默认为null。 User表有username,id,phone,email,password字段,只修改usernam和phone, 修改操作: 1.拿到前端传递的实体user; 2.根据user的userId,拿到原始的对象(修改前的user对象); Long userId = user.getUser...
hibernate的saveOrUpdate,返回void,而merge是返回一个对象。 saveOrUpdate,会根据id判断是否持久化过,来Save或者update。之后对象就成为持久化状态。 而merge只是将对象保存到数据库,并没有成为持久化状态。 jpa的persist ,必须配合@version 版本来使用。如果没有而直接persist,那么会报detached e
JPA的部分字段更新问题 由于JPA没有update的相关方法,所以update操作在JPA中是用的save()方法。原理就是每次save()会先执行一次select语句,查询在数据库中有没有存在主键相同的记录,若有就执行update操作,若没有就执行insert操作。 就因为上述逻辑,就导致了每次执行save()方法,所传入的实体对象必须是完整的,此处完整的含义是实体对象和数据库的记录的字段值要完全对应起来,否则的话就有可能这次我只想更新A字段,传入的对象的属性就A字段有值,B和C字段为null没有赋
这里我解释下序图的意思: A系统是我这里负责的系统,B系统是我的下游,在客户预约间之后,我首先会把客户的预约间存到数据库的订单表里面,这是序图中第一步做的事情 第二步:会把这个间同步给下游,这里就是一个简单的dubbo接口的调用 第三步,我这里会接着处理其他的一些逻辑,但是有一个问题:1、2、3这三步,是在同一个事务里面,这样的话,只有在1、2、3全部完成的候, 1.2 操作 其实在SpringDataJPA中,保存和更新都使用的是 save(S s)方法,下面我们看demo. 我在user_info表中添加个用户Helena,然后修改其用户名为Helena1. 1.2.1 添加用户Helena @Test void sav... 卡了好几天 原来是实体类的问题 间没加@Temporal(TemporalType.TIMESTAMP)这个注解 加了之后就好了 数据库存的是timestamp 实体类是date
1.由于项目用到了spring data jpa,新增修改都可以用save()方法,于是在修改的候也用了save()方法 2.想着修改的候只更新更新间,创建间不更新,这样可以看出是否被修改过,于是代码没有设置创建间,以为可以自动获取创建的创建间 3.测试了修改接口也没问题,但是由于本人 考虑问题不全面,比较粗心,没有检查数据库中的数据,导致线上出现了NullPointerException 4.经排查是修改的候导致的created_time为null 5.于是再次学习了data jp