一 点睛
我们对数据库进行操作时,新增和修改是一对孪生兄弟,大多数情况下新增后会再次对新增的数据进行维护,这时修改就派上用场了。
另外新增和修改如果没用好,往往会出现插入时主键重复,或更新时,不存在数据或存在多条数据的情况,这些都会导致异常。
因为经常会用这种场景,这里做个总结。
二 数据库设计
我们把数据库设计成下面这个样子,其中id是主键,另外我们还规定username和title唯一确定一条记录,我们称(username,title)为业务主键,为了提高性能,我们可以将(username,title)设为索引。
Name
|
记录文章列表
|
|||||
Code
|
News
|
|||||
Table
|
news
|
|||||
Memo
|
描述新闻信息
|
|||||
Group
|
Name
|
Column Name
|
Data Type
|
Dictionary
|
Not Null
|
Memo
|
基本属性组
|
标识
|
id
|
Varchar(100)
|
|
Y
|
UUID
|
实体关系属性组
|
用户名
|
username
|
{FK}
|
|
Y
|
|
特征属性组
|
标题
|
title
|
Varchar(100)
|
|
Y
|
|
|
内容
|
content
|
Varchar(100)
|
|
Y
|
|
三 业务场景分析
1 首先当然是要把新文章以新增的方式加到数据表。
2 文章日后可以修改内容,但不能修改标题。这个时候修改就派上用场了。
四 在Mybatis-plus中可以这样写代码
@Override
public void add( NewsDTO newsDTO ) {
try {
News news;
try {
// 更新情况
news = detail(newsDTO.getUsername(), newsDTO.getTitle());
news.setContent(newsDTO.getContent());
} catch (Exception e) {
// 新增情况
news = new News();
news.setTitle(newsDTO.getTitle());
news.setContent(newsDTO.getContent());
news.setUsername(newsDTO.getUsername());
}
this.saveOrUpdate(news);
} catch (Exception e) {
log.info(e.getMessage());
throw new RequestException(ResponseCode.SQL_FAIL);
}
}
@Override
public News detail( String username, String title ) {
try {
return this.getOne(Wrappers.<News>lambdaQuery().eq(News::getUsername, username).eq(News::getTitle, title));
} catch (RuntimeException e) {
throw new RequestException(ResponseCode.TOO_MANY_RESULTS);
}
}
这样写可以实现新增,也能根据业务主键先找到要修改的记录,然后更新相关内容。最后统一通过IService的saveOrUpdate实现统一新增或修改。但总觉得把新增记录写在catch里不是太优雅。而且还要实现一个detail方法,不是太好,有没有更好的方法呢?
经过尝试, 先通过Lambda实现更新,如果更新失败,再通过BaseMapper接口的insert实现新增。可以解决上面提到的两个问题,而且代码更简单。
// 下面是通过BaseMapper接口的insert实现新增,update实现根据业务主键修改
@Override
public void add( NewsDTO newsDTO ) {
try {
// 更新情况:先更新一把,如果能更新成功,就说明是更新情况,否则就是新增情况
boolean flag = new LambdaUpdateChainWrapper<News>(newsMapper)
.eq(News::getTitle, newsDTO.getTitle())
.eq(News::getUsername, newsDTO.getUsername())
.set(News::getContent, newsDTO.getContent()).update();
log.info("flag is "+flag);
// 新增情况:如果不能更新成功
if (!flag) {
News news = new News();
news.setTitle(newsDTO.getTitle());
news.setContent(newsDTO.getContent());
news.setUsername(newsDTO.getUsername());
newsMapper.insert(news);
}
} catch (Exception e) {
throw new RequestException(ResponseCode.SQL_FAIL);
}
}
来源:oschina
链接:https://my.oschina.net/u/4280983/blog/4269953