刚刚接触到了mongodb数据库,对于mongodb的操作以前没有了解,这里也是接触到了Spring提供的Spring Data Jpa工程,使用Spring Data Jpa来对mongodb进行一些增删改查,因为了解的不多,这里记录了一些简单的增删改查。
先了解什么是JPA?
JPA(Java Persistence API)是Sun官方提出的Java持久化规范。它为Java开发人员提供了一种对象/关联映射工具来管理Java应用中的关系数据。他的出现主要是为了简化现有的持久化开发工作和整合ORM技术,结束现在Hibernate,TopLink,JDO等ORM框架各自为营的局面。值得注意的是,JPA是在充分吸收了现有Hibernate,TopLink,JDO等ORM框架的基础上发展而来的,具有易于使用,伸缩性强等优点。从目前的开发社区的反应上看,JPA受到了极大的支持和赞扬,其中就包括了Spring与EJB3.0的开发团队。
重点:JPA是一套规范,不是一套产品。
Spring Data JPA 是 Spring 基于 ORM 框架、JPA 规范的基础上封装的一套JPA应用框架,可使开发者用极简的代码即可实现对数据的访问和操作。它提供了包括增删改查等在内的常用功能,且易于扩展,使用它可以提高我们的开发效率。基本上所有CRUD都可以依赖于它来实现。
需要配置连接到mongodb的信息,如下:
spring: ## mongodb连接配置 data: mongodb: uri: mongodb://user40642330:xxxxxxx@dds-bp12ailpzf1ijx8u-pub.mongodb.rds.aliyuncs.com:3717 database: test_ycz
我用的是阿里云的mongodb产品。
因为我的model是单独分一个工程出去的,所有pojo都在这个工程中定义,所以在pojo所在的工程需要先添加依赖,为什么要加依赖?因为要使用它的注解。
<!-- data-mongodb依赖 --> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-mongodb</artifactId> <version>3.1.1</version> </dependency>
然后pojo实体类如下:
@Document(collection = "music_detail") public class MusicDetail { @Id @Getter @Setter private String musicId;//音乐ID @Getter @Setter private String musicName;//音乐名称 @Getter @Setter private String musicType;//音乐类型 @Getter @Setter private String author;//音乐表演者 @Getter @Setter private String album;//所属专辑 @Getter @Setter private Date addTime;//添加时间 }
@Id和@Document是它提供的注解。
因为后期我要使用参数来查询,所以这里封装了一个查询对象,所有的查询参数都封装在这个对象中,如下:
/* * 此类型用来接收查询参数 */ @Data public class QueryRequest { //音乐名称 private String musicName; //音乐类型 private String musicType; //专辑 private String album; //作者 private String author; }
@Api(value = "音乐信息管理",description = "提供音乐的增删改查",tags = {"音乐信息管理"}) public interface MusicControllerApi { @ApiOperation("音乐信息添加") ResponseResult addMusic(MusicDetail musicDetail); @ApiOperation("音乐信息修改") ResponseResult editMusic(String musicId,MusicDetail musicDetail); @ApiOperation("音乐信息删除") ResponseResult delMusic(String musicId); @ApiOperation("按指定条件查询并且分页") QueryResponseResult<MusicDetail> getMusic(int page,int size,QueryRequest queryRequest); }
这里简单的定义了4个接口,测试增删改查,api我是单独分了一个api工程出去的。
package com.ycz.swagger.dao; import org.springframework.data.mongodb.repository.MongoRepository; import com.ycz.domain.music.MusicDetail; public interface MusicDetailRepository extends MongoRepository<MusicDetail, String>{ //通过作者和歌名查询 MusicDetail findByMusicNameAndAuthor(String musicName,String author); }
直接定义一个接口来继承MongoRepository就行了,第一个参数是collection对应的实体类,第二个参数是主键类型,这里我定义了一个简单接口,来做添加前的简单判断。
@Service public class MusicDetailService { @Autowired MusicDetailRepository musicDetailRepository; //添加音乐信息 public ResponseResult addMusic(MusicDetail musicDetail) { // 先查询 MusicDetail music = musicDetailRepository. findByMusicNameAndAuthor(musicDetail.getMusicName(), musicDetail.getAuthor()); if(music!=null) { return new ResponseResult(CommonCode.FAIL); } musicDetail.setAddTime(new Date()); musicDetailRepository.save(musicDetail); return new ResponseResult(CommonCode.SUCCESS); } //修改音乐信息 public ResponseResult editMusic(String musicId, MusicDetail musicDetail) { //先查询 Optional<MusicDetail> optional = musicDetailRepository.findById(musicId); if(!optional.isPresent()) { return new ResponseResult(CommonCode.FAIL); } //执行修改保存 MusicDetail music = optional.get(); music.setMusicName(musicDetail.getMusicName()); music.setMusicType(musicDetail.getMusicType()); music.setAuthor(musicDetail.getAuthor()); music.setAlbum(musicDetail.getAlbum()); musicDetailRepository.save(music); return new ResponseResult(CommonCode.SUCCESS); } //执行删除 public ResponseResult delMusic(String musicId) { // 先查询 Optional<MusicDetail> optional = musicDetailRepository.findById(musicId); if(!optional.isPresent()) { return new ResponseResult(CommonCode.FAIL); } //删除 musicDetailRepository.deleteById(musicId); return new ResponseResult(CommonCode.SUCCESS); } //按条件查询,并且分页 public QueryResponseResult<MusicDetail> getMusic(int page, int size, QueryRequest queryRequest) { // 判断查询条件非空 if(queryRequest==null) { queryRequest = new QueryRequest(); } //创建条件值对象 MusicDetail music = new MusicDetail(); //按照作者、音乐名称、专辑名模糊查询 //定义条件匹配器 ExampleMatcher exampleMatcher = ExampleMatcher.matching(). withMatcher("author", GenericPropertyMatchers.contains()). withMatcher("musicName", GenericPropertyMatchers.contains()). withMatcher("album", GenericPropertyMatchers.contains()); //在条件匹配器中我没有设置musicType这个参数 //没有设置的话它默认是按精确匹配 //判断各参数是否为空 if(StringUtils.isNotEmpty(queryRequest.getMusicType())) { music.setMusicType(queryRequest.getMusicType()); } if(StringUtils.isNotEmpty(queryRequest.getMusicName())) { music.setMusicName(queryRequest.getMusicName()); } if(StringUtils.isNotEmpty(queryRequest.getAlbum())) { music.setAlbum(queryRequest.getAlbum()); } if(StringUtils.isNotEmpty(queryRequest.getAuthor())) { music.setAuthor(queryRequest.getAuthor()); } //基于值对象和匹配器定义条件对象 Example<MusicDetail> example = Example.of(music, exampleMatcher); if(page<=0) { page = 1; } //page=0代表第1页,所以这里要从0开始 page = page - 1; if(size<=5) { size = 5; } //分页 Pageable pageable = PageRequest.of(page, size); //获取分页对象 Page<MusicDetail> all = musicDetailRepository.findAll(example, pageable); //获取总的记录条数 long total = all.getTotalElements(); //获取查询列表 List<MusicDetail> list = all.getContent(); //封装对象 QueryResult<MusicDetail> queryResult = new QueryResult<MusicDetail>(); queryResult.setTotal(total); queryResult.setList(list); return new QueryResponseResult<>(CommonCode.SUCCESS, queryResult); } }
@RestController @RequestMapping("/music") public class MusicController implements MusicControllerApi{ @Autowired MusicDetailService musicDetailService; @Override @PostMapping("/addMusic") public ResponseResult addMusic(@RequestBody MusicDetail musicDetail) { return musicDetailService.addMusic(musicDetail); } @Override @PutMapping("/editMusic/{musicId}") public ResponseResult editMusic(@PathVariable("musicId") String musicId, @RequestBody MusicDetail musicDetail) { return musicDetailService.editMusic(musicId,musicDetail); } @Override @DeleteMapping("/delMusic/{musicId}") public ResponseResult delMusic(@PathVariable("musicId") String musicId) { return musicDetailService.delMusic(musicId); } @Override @GetMapping("/getMusic/list/{page}/{size}") public QueryResponseResult<MusicDetail> getMusic( @PathVariable("page") int page, @PathVariable("size") int size, QueryRequest queryRequest) { return musicDetailService.getMusic(page,size,queryRequest); } }
这个控制器统一返回json数据,实现了api工程中新定义的接口,接口在这里暴露出来。
使用swagger进行测试,
浏览器进入:http://localhost:10000/swagger-ui.html
返回结果:
返回结果:
返回结果:
测试查询:
这里先不设其他参数,只设置分页的page和size,结果太长,截不了图,用代码贴出:
{ "success": true, "code": 10000, "message": "操作成功!", "queryResult": { "list": [ { "musicId": "5fe47e2100739f6474c19422", "musicName": "晚晴润雨", "musicType": "pure", "author": "陈致逸", "album": "天涯明月刀", "addTime": "2020-12-24T11:40:16.948+00:00" }, { "musicId": "5fe47e8300739f6474c19423", "musicName": "云水逸", "musicType": "pure", "author": "张晓红", "album": "古筝爱好者", "addTime": "2020-12-24T11:41:55.952+00:00" }, { "musicId": "5fe47ed600739f6474c19424", "musicName": "雪满山中", "musicType": "pure", "author": "忘乡", "album": "雪满山中", "addTime": "2020-12-24T11:43:18.411+00:00" }, { "musicId": "5fe47f0a00739f6474c19425", "musicName": "峨眉金顶", "musicType": "pure", "author": "卢小旭", "album": "蜀山OL原乐声", "addTime": "2020-12-24T11:44:10.881+00:00" }, { "musicId": "5fe47f3800739f6474c19426", "musicName": "鸿迹", "musicType": "pure", "author": "变奏的梦想", "album": "鸿迹", "addTime": "2020-12-24T11:44:56.743+00:00" }, { "musicId": "5fe47f5400739f6474c19427", "musicName": "比翼鸟", "musicType": "pure", "author": "麦振鸿", "album": "武侠音乐之喜气洋洋", "addTime": "2020-12-24T11:45:24.505+00:00" }, { "musicId": "5fe47f8600739f6474c19428", "musicName": "御史秦风云", "musicType": "pure", "author": "霹雳布袋戏", "album": "霹雳布袋戏", "addTime": "2020-12-24T11:46:14.611+00:00" }, { "musicId": "5fe4808c00739f6474c19429", "musicName": "轻风", "musicType": "pure", "author": "四季春色", "album": "春夏之交,轻旋淡律", "addTime": "2020-12-24T11:50:36.700+00:00" }, { "musicId": "5fe480dc00739f6474c1942a", "musicName": "潇湘子", "musicType": "pure", "author": "霹雳布袋戏", "album": "霹雳英雄", "addTime": "2020-12-24T11:51:56.745+00:00" }, { "musicId": "5fe4812000739f6474c1942b", "musicName": "该不该难过", "musicType": "sing", "author": "魏枫", "album": "该不该难过", "addTime": "2020-12-24T11:53:04.673+00:00" } ], "total": 17 } }
可以看到,查询的一共17条记录,我数据库中也只有17条记录,但是返回的是第1页,因为设置了分页参数。
返回结果:
{ "success": true, "code": 10000, "message": "操作成功!", "queryResult": { "list": [ { "musicId": "5fe47f8600739f6474c19428", "musicName": "御史秦风云", "musicType": "pure", "author": "霹雳布袋戏", "album": "霹雳布袋戏", "addTime": "2020-12-24T11:46:14.611+00:00" }, { "musicId": "5fe480dc00739f6474c1942a", "musicName": "潇湘子", "musicType": "pure", "author": "霹雳布袋戏", "album": "霹雳英雄", "addTime": "2020-12-24T11:51:56.745+00:00" } ], "total": 2 } }
查到2条记录,专辑霹雳布袋戏、霹雳英雄这2条记录。
返回结果:
{ "success": true, "code": 10000, "message": "操作成功!", "queryResult": { "list": [ { "musicId": "5fe4823500739f6474c1942d", "musicName": "爱笑的女孩", "musicType": "sing", "author": "杨陆", "album": "爱笑的女孩", "addTime": "2020-12-24T11:57:41.780+00:00" } ], "total": 1 } }
结果正确,和数据库中记录是匹配的。
使用Spring Data Mongodb可以非常快速简便的对mongodb中的collection进行CRUD,大大提高了我们的开发效率,目前刚用,只是有一个简单的了解,相信它并不只有这么点功能,以后继续了解深入。