Mybatis-plus中对新增和修改的思考

点点圈 提交于 2020-05-08 09:57:58
一 点睛
我们对数据库进行操作时,新增和修改是一对孪生兄弟,大多数情况下新增后会再次对新增的数据进行维护,这时修改就派上用场了。
另外新增和修改如果没用好,往往会出现插入时主键重复,或更新时,不存在数据或存在多条数据的情况,这些都会导致异常。
因为经常会用这种场景,这里做个总结。
二 数据库设计
我们把数据库设计成下面这个样子,其中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);
    }
}

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!