ON DUPLICATE KEY UPDATE demo

关于一个mybaits一个sql标签实现 既可以插入新的动态,又可以更新原来的动态。

我新建了一个表,让id为主键,id主键为自增。当前端插入新的一条动态时可以直接插入,当修改已有的动态时,根据获取的id判断原来的表中已经存了,则应该执行ON DUPLICATE KEY UPDATE.

ON DUPLICATE KEY UPDATE

<update id="saveOrUpdate" parameterType="com.second.hand.trading.server.model.NoticeModel">
        insert into notice (id,name,content,user,time,img)
        values (#{id,jdbcType=VARCHAR},#{name,jdbcType=VARCHAR},#{content,jdbcType=VARCHAR},#{user,jdbcType=VARCHAR},#{time,jdbcType=TIMESTAMP},#{img,jdbcType=VARCHAR})
        ON DUPLICATE KEY UPDATE
            name=VALUES(name),
            content=VALUES(content),
            user=VALUES(user),
             img=VALUES(img),

    update>

现在的问题时,新增的时候,id主键没有自增,id主键值还得赋值,但是前端应该如何实现呢?

前端代码


//表格输入的信息
handleAdd() {
      this.dialogFormVisible = true
      this.form = {img: ''}
      this.$nextTick(() => {
        if(!editor) {
          editor = new E("#richText")
          editor.config.uploadImgServer = 'http://localhost:8080/file/'
          editor.config.uploadFileName = 'file'
          editor.create()
        }
        editor.txt.html('')  // 清除内容

        if(this.$refs.img) {
          this.$refs.img.clearFiles();
        }
        if(this.$refs.file) {
          this.$refs.file.clearFiles();
        }
      })
    },


```java

    save() {
      const content = editor.txt.html()
      console.log(content)
      // 注意:这个地方需要手动赋值
      this.form.content = content
      //保存或修改内容
      this.$api.savenotice(this.form).then(res => {
        if (res.status_code === 1) {
          this.$message.success("保存成功")
          this.dialogFormVisible = false
          this.load()
        } else {
          this.$message.error("保存失败")
        }
      })
    },

```

在前端实现上,可以考虑在插入新动态时,将id字段设置为null或者不填写,这样数据库会自动为该字段分配一个自增的id。而在修改已有动态时,前端应该将要修改的动态的id值传入后台,让后台根据id值来执行ON DUPLICATE KEY UPDATE语句更新数据库中对应的记录。

修改前端代码如下:

handleAdd() {
  this.dialogFormVisible = true
  this.form = {id: null, img: ''}
  this.$nextTick(() => {
    if(!editor) {
      editor = new E("#richText")
      editor.config.uploadImgServer = 'http://localhost:8080/file/'
      editor.config.uploadFileName = 'file'
      editor.create()
    }
    editor.txt.html('')  // 清除内容

    if(this.$refs.img) {
      this.$refs.img.clearFiles();
    }
    if(this.$refs.file) {
      this.$refs.file.clearFiles();
    }
  })
},

save() {
  const content = editor.txt.html()
  console.log(content)
  // 注意:新增时不传id字段,数据库会自动为该字段分配一个自增的id;修改时传入id字段,用于更新已有记录
  if (this.form.id) {
    this.$api.updateNotice(this.form).then(res => {
      if (res.status_code === 1) {
        this.$message.success("修改成功")
        this.dialogFormVisible = false
        this.load()
      } else {
        this.$message.error("修改失败")
      }
    })
  } else {
    this.$api.saveNotice({...this.form, content}).then(res => {
      if (res.status_code === 1) {
        this.$message.success("保存成功")
        this.dialogFormVisible = false
        this.load()
      } else {
        this.$message.error("保存失败")
      }
    })
  }
},


同时,后端的代码也需要进行一些修改,需要在Service中添加一个新的方法用于更新已有记录,并在Controller中增加一个新的处理方法。例如:

// Service.java
public interface Service {
    public void execute(HttpServletRequest request, HttpServletResponse response, ServletContext context)
        throws Exception;
    public void updateNotice(NoticeModel notice) throws Exception;
}

// ServiceImpl.java
public class ServiceImpl implements Service {
    // ...
    public void updateNotice(NoticeModel notice) throws Exception {
        String sql = "INSERT INTO notice (id, name, content, user, time, img) VALUES (?, ?, ?, ?, ?, ?) " +
            "ON DUPLICATE KEY UPDATE name=VALUES(name), content=VALUES(content), user=VALUES(user), img=VALUES(img)";
        jdbcTemplate.update(sql, notice.getId(), notice.getName(), notice.getContent(), notice.getUser(), notice.getTime(), notice.getImg());
    }
    // ...
}

// Controller.java
public class Controller extends HttpServlet {
    // ...
    public void update(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String id = request.getParameter("id");
        String name = request.getParameter("name");
        String content = request.getParameter("content");
        String user = request.getParameter("user");
        String img = request.getParameter("img");

        NoticeModel notice = new NoticeModel();
        notice.setId(id);
        notice.setName(name);
        notice.setContent(content);
        notice.setUser(user);
        notice.setImg(img);

        ServletContext context = getServletContext();
       try {
        service.updateNotice(notice);
        response.getWriter().write("success");
    } catch (Exception e) {
        e.printStackTrace();
        response.getWriter().write("fail");
    }
}

在前端代码中,可以看到在调用 this.$api.savenotice(this.form) 时将 this.form 对象作为参数传递给了后端。在后端的 Controller 类中,可以通过 HttpServletRequest 对象获取到前端传递过来的参数值,然后将其设置到 NoticeModel 对象中,并调用 Service 接口中的 updateNotice 方法进行保存或更新操作。具体实现可以参考上述代码。

  • 这篇博客: ON DUPLICATE KEY UPDATE 作用及一句SQL实现批量修改中的 用法 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 举个栗子:

    table1表中有几条数据如下:
    在这里插入图片描述表中的主键为ID,现要插入一条数据,ID为4,name为修改4,password为xiugaimima4,正常写法为:

    INSERT INTO table1(`id`,`name`,`password`,`date`)
    VALUES('4','修改4','xiugaimima4',now());
    

    执行后刷新表数据,我们来看表中内容:
    在这里插入图片描述
    此时表中数据增加了一条主键为id为’1’,name为’修改4’,password为’xiugaimima4’的记录,当我们再次执行插入语句时,会发生什么呢?

    执行:

    INSERT INTO table1(`id`,`name`,`password`,`date`)
    VALUES('4','修改4','xiugaimima4',now());
    

    在这里插入图片描述

    MySQL告诉我们,我们的主键冲突了,看到这里我们是不是可以改变一下思路,当插入已存在主键的记录时,将插入操作变为修改:

    在原SQL后面增加 ON DUPLICATE KEY UPDATE

    INSERT INTO table1(`id`,`name`,`password`,`date`)
    VALUES('4','修改4','xiugaimima4',now())
    ON DUPLICATE KEY UPDATE
    id='5',password='xiugaimima5';
    

    我们再一次执行:
    在这里插入图片描述
    可以看到,受影响的行为2,这是因为将原有的记录修改了,而不是执行插入,看一下表中数据:

    在这里插入图片描述

    原来id4的记录,改为了5,password也变为了xiugaimima5,很好的解决了重复插入问题。