关于on duplicate key update使用中遇到的坑

使用场景:在一张表中,有2条数据重复。排查发现,是由于jms消费时,由于多个一样的消息同时消费,而在消费代码中,处理逻辑比较复杂,导致事务比较长,因此就会出现并发。

消费代码逻辑块中,有包含以下逻辑:

Student student = studentService.getEntityByName(name);

if(null==student){

student = new Student();

 

student.setName("aa");

...

this.save(student);

}else{

student.setUpdateTime(new Date());

...

this.update(student);

}

此时线程A消费消息A。线程B消费消息B。(消息A和消息B数据一模一样)。则正常结果应该是student表只有1条数据。但是如果消费及时,就有可能线程A和线程B在执行到上述代码块时,从数据库查询到的student对象都是null,则就会出现数据库保存了2条student。原因是:线程A事务还没提交,而线程B获取不到线程A的对象。

 

解决方案:

Student studeng = studentService.getEntityByName(name);
if(null == student){
    student.setName("aa");
    ...
}else{
    studeng.setUpdateTime(new Date());
}
studentDao.saveOrUpdate(student);

studentDao:
public void saveOrUpdate(Student student){
    Map<String, Object> params = new HashMap<>(8);
    StringBuffer sql = new StringBuffer("insert into studeng(id, name,updateTime, count)");
    sql.append(" values(:id, :name,:updateTime, :count)");
    sql.append(" on duplicate key update count=(count+1)");
    params.put("id", student.getId());
    params.put("name", student.getName());
    params.put("updateTime", student.getUpdateTime());
    params.put("count", student.getCount());
    createSqlQuery(sql.toString(),params).executeUpdate();
}
这种去执行测试,发现,在代码update后面,并没有要更新时间,但是代码执行后,updateTime时间却改变了,而count值并没有被修改到。折腾了好久,才发现问题所在。原因是studeng.setUpdateTime(new Date());这句影响到(至于为什么这句会影响到执行结果,目前还不知道………………)。因此将上面的代码修改为:
Student studeng = studentService.getEntityByName(name);
if(null == student){
    student.setName("aa");
    ...
}
studentDao.saveOrUpdate(student);

studentDao:
public void saveOrUpdate(Student student){
    Map<String, Object> params = new HashMap<>(8);
    StringBuffer sql = new StringBuffer("insert into studeng(id, name,updateTime, count)");
    sql.append(" values(:id, :name,:updateTime, :count)");
    sql.append(" on duplicate key update updateTime=:updateTime, count=(count+1)");
    params.put("id", student.getId());
    params.put("name", student.getName());
    if(student.getId() != 0){
        params.put("updateTime", new Date());
    }else{
        params.put("updateTime", student.getUpdateTime());
    }
    params.put("count", student.getCount());
    createSqlQuery(sql.toString(),params).executeUpdate();
}
改为这样,便可正常执行count+1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值