关于一个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 方法进行保存或更新操作。具体实现可以参考上述代码。
举个栗子:
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,这是因为将原有的记录修改了,而不是执行插入,看一下表中数据:
原来id
为4的记录,改为了5,password也变为了xiugaimima5,很好的解决了重复插入问题。