Spring Data CRUD

时间:2024-11-30 18:12:17

在配置完毕 MongoDB 以后,就可以编程操作了。

对数据库的操作一定要放在 @Service 类中,而不是放在 @Controller 类中;且 @Controller 类可以调用 @Service 类的方法,反之则不行。这是 SpringMVC 的经典架构设计理念。

  • @Service 类主要用于不易变的核心业务逻辑。
  • @Controller 类与前端页面紧密配合,调用 @Service 服务读写数据,从而响应前端请求,

这个设计大家可能目前没有体会,但是没关系,希望在学习、实战中持续理解和思考。

1. 新增数据

新增数据就是向数据库中插入一条数据。在 Java 世界中万物皆对象,所以,所谓数据就是实例对象。

import org.springframework.data.mongodb.core.MongoTemplate;

  @Autowired
  private MongoTemplate mongoTemplate;

  public void test() {
    Song song = new Song();
    song.setSubjectId("s001");
    song.setLyrics("...");
    song.setName("成都");

    mongoTemplate.insert(song);
  }

在本课程第 2 章已经学过,使用 @Autowired 可以让系统自动注入 MongoTemplate 的实例。

只需要调用 mongoTemplate.insert() 方法就能把对象存入数据库。非常简单。

页面上打印出了新增的结果歌曲,系统会自动为 id 属性(主键)赋值:

{"songResult":{"id":"5e55db3a461b9b3c3e1d6a56","name":"成都","lyrics":"...","subjectId":"s001"}}

2. 查询数据

一条语句就可以了:

mongoTemplate.findById(songId, Song.class)

注意:findById() 方法第 1 个参数就是主键 id,第 2 个参数是具体的类,写法是 类名.class

3. 修改数据

修改数据的语句就略复杂一些了。因为修改的操作包括两个部分:

  1. 修改哪条数据?
  2. 哪个字段修改成什么值?

所以,修改操作也分为部分:修改条件和修改的字段。

// 修改 id=1 的数据
Query query = new Query(Criteria.where("id").is("1"));

// 把歌名修改为 “new name”
Update updateData = new Update();
updateData.set("name", "new name");

// 执行修改,修改返回结果的是一个对象
UpdateResult result = mongoTemplate.updateFirst(query, updateData, Song.class);
// 修改的记录数大于 0 ,表示修改成功
System.out.println("修改的数据记录数量:" + result.getModifiedCount());

先使用条件对象 Criteria 构建条件对象 Query 实例,然后在调用修改对象 Update 的方法 .set() 设置需要修改的字段。

最后调用 mongoTemplate.updateFirst(query, updateData, Song.class) 方法完成修改;第 3 个参数是具体的类。

本修改数据的演示中, 使用了约定:主键不能修改;且其它字段值为 null 表示不修改,值为长度为 0 的字符串 "" 表示清空此字段。

这样,我们就可以使用一个 Song 对象区分出“哪些字段需要修改”、“哪些字段不需要修改”、“哪些字段需要清除值”等多种情况。服务接口只需要 Song 对象一个参数即可,使用起来也比较简便。

大家需要思考和体会这段逻辑,在今后的工作中能够根据实际情况灵活运用哦。

4. 删除数据

删除数据也比较简单,只需要精确确定需要删除哪什么数据即可。

调用 mongoTemplate.remove() 方法即可删除数据,参数是对象,表示需要删除哪些数据。

示例代码:

Song song = new Song();
song.setId(songId);

// 执行删除
DeleteResult result = mongoTemplate.remove(song);
// 删除的记录数大于 0 ,表示删除成功
System.out.println("删除的数据记录数量:" + result.getDeletedCount());

创建一个对象并设置好属性值,作为删除的条件,符合条件的数据都将被删除。可以设置更多的属性值来提高精确性,但通过主键来删除数据,是保证不误删的一个比较好的办法。

删除数据一定要谨慎哦

由于第一步执行新增数据, ID 是成动态生的,所以一步不知道具体该删除哪一条数据,所以会失败。但是没关系,接下来的作业中自己实现并验证。

数据库操作中,用的最少的操作是删除,用的最多的操作就是查询了,除了根据主键查询,更多的是需要根据条件查询。

.imp-->im.java-->control

package fm.douban.app.control;

import com.alibaba.fastjson.JSON;
import fm.douban.model.Song;
import fm.douban.service.SongService;
import fm.douban.service.SubjectService;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.PostConstruct;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class SongListControl {

  private static final Logger LOG = LoggerFactory.getLogger(SongListControl.class);

  @Autowired
  private SubjectService subjectService;

  @Autowired
  private SongService songService;

  @PostConstruct
  public void init() {
    LOG.error("SongListControl 启动啦");
    if (subjectService != null) {
      LOG.info("subjectService 实例注入成功。");
    } else {
      LOG.info("subjectService 实例注入失败。");
    }
  }

  @RequestMapping("/songadd")
  public Map add() {
    Map returnData = new HashMap();
    Song song=new Song();
    song.setLyrics("...");
    song.setName("ykd");
    song.setSubjectId("001");
    Song songResult = songService.add(song);
    returnData.put("songResult", songResult);
    return returnData;
  }

  @RequestMapping("/songget")
  public Map get(@RequestParam String id) {
    Map returnData = new HashMap();
    Song songResult = songService.get(id);

    returnData.put("songResult", songResult);
    return returnData;
  }

  @RequestMapping("/songmodify")
  public Map modify(@RequestParam String id) {
    Map returnData = new HashMap();

    Song song = new Song();
    // 必须指定修改哪一条数据
    song.setId(id);
    // 仅演示:用一个随机数代替歌词
    song.setLyrics(String.valueOf(Math.random()));
    boolean result = songService.modify(song);

    returnData.put("modify_success", result);
    return returnData;
  }

  @RequestMapping("/songdelete")
  public Map delete(@RequestParam String id) {
    Map returnData = new HashMap();
    boolean result = songService.delete(id);

    returnData.put("delete_success", result);
    return returnData;
  }

  private Song buildSong() {
    Song song = new Song();
    // song 对象的 id 主键不要赋值,MongoDB 会自动填入唯一的随机字符串
    song.setSubjectId("s001");
    song.setLyrics("...");
    song.setName("成都");
    song.setId("001");
    Song songResult = songService.add(song);

    return songResult;
  }

  @RequestMapping("/songcheck")
  public Map check() {
    Map returnData = new HashMap();

    // 新增一条数据,失败则中断
    Song addedSong = buildSong();
    String id = addedSong.getId();
    returnData.put("add_song_id", id);
    if (id != null) {
      returnData.put("add_result", true);
    } else {
      returnData.put("add_result", false);
      return returnData;
    }

    // 读取刚刚新增的数据
    Song getResult = songService.get(id);
    if (getResult != null) {
      returnData.put("get_result", true);
    } else {
      returnData.put("get_result", false);
      return returnData;
    }

    getResult.setName("成都-2");
    getResult.setLyrics("......");

    boolean modifyResult = songService.modify(getResult);
    Song modifiedSong = songService.get(id);
    if (modifyResult && modifiedSong != null && "成都-2".equals(modifiedSong.getName())
        && "......".equals(modifiedSong.getLyrics())) {
      returnData.put("modify_result", true);
    } else {
      returnData.put("modify_result", false);
      return returnData;
    }

    boolean delResult = songService.delete(id);
    Song deletedSong = songService.get(id);
    if (delResult && deletedSong == null) {
      returnData.put("delete_result", true);
    } else {
      returnData.put("delete_result", false);
    }

    LOG.info("check song CRUD service result");
    LOG.info(JSON.toJSONString(returnData));
    return returnData;
  }

}

package fm.douban.service.impl;

import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import fm.douban.model.Song;
import fm.douban.service.SongService;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

@Service
public class SongServiceImpl implements SongService {

  private static final Logger LOG = LoggerFactory.getLogger(SongServiceImpl.class);

  @Autowired
  private MongoTemplate mongoTemplate;//实例注入

  @Override
  public Song add(Song song) {
    return mongoTemplate.insert(song);
  }

  @Override
  public Song get(String songId) {
    return mongoTemplate.findById(songId,Song.class);
  }

  @Override
  public List<Song> list(Song songParam) {
    // 本节课暂时不用修改
    List<Song> songs = new ArrayList<>();

    return songs;
  }

  @Override
  public boolean modify(Song song) {
    Query query=new Query(Criteria.where("id").is(song.getId()));
    Update update=new Update();
    update.set("name",song.getName());
    UpdateResult updateResult=mongoTemplate.updateFirst(query,update,Song.class);
    return updateResult!=null&&updateResult.getModifiedCount()>0;

  }

  @Override
  public boolean delete(String songId) {
    Song song=new Song();
    song.setId(songId);
    DeleteResult result=mongoTemplate.remove(song);
    return result!=null&&result.getDeletedCount()>0;

  }

}