前言
刚刚接触到了mongodb数据库,对于mongodb的操作以前没有了解,这里也是接触到了Spring提供的Spring Data Jpa工程,使用Spring Data Jpa来对mongodb进行一些增删改查,因为了解的不多,这里记录了一些简单的增删改查。
1、JPA
先了解什么是JPA?
JPA(Java Persistence API)是Sun官方提出的Java持久化规范。它为Java开发人员提供了一种对象/关联映射工具来管理Java应用中的关系数据。他的出现主要是为了简化现有的持久化开发工作和整合ORM技术,结束现在Hibernate,TopLink,JDO等ORM框架各自为营的局面。值得注意的是,JPA是在充分吸收了现有Hibernate,TopLink,JDO等ORM框架的基础上发展而来的,具有易于使用,伸缩性强等优点。从目前的开发社区的反应上看,JPA受到了极大的支持和赞扬,其中就包括了Spring与EJB3.0的开发团队。
重点:JPA是一套规范,不是一套产品。
2、Spring Data Jpa是什么
Spring Data JPA 是 Spring 基于 ORM 框架、JPA 规范的基础上封装的一套JPA应用框架,可使开发者用极简的代码即可实现对数据的访问和操作。它提供了包括增删改查等在内的常用功能,且易于扩展,使用它可以提高我们的开发效率。基本上所有CRUD都可以依赖于它来实现。
3、Spring Data Jpa的使用
(1)yml配置
需要配置连接到mongodb的信息,如下:
spring:
## mongodb连接配置
data:
mongodb:
uri: mongodb://user40642330:xxxxxxx@dds-bp12ailpzf1ijx8u-pub.mongodb.rds.aliyuncs.com:3717
database: test_ycz
我用的是阿里云的mongodb产品。
(2)pojo
因为我的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;
}
(3)api
@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工程出去的。
(4)dao
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对应的实体类,第二个参数是主键类型,这里我定义了一个简单接口,来做添加前的简单判断。
(5)Service
@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);
}
}
(6)Controller
@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工程中新定义的接口,接口在这里暴露出来。
(7)测试
使用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条记录。
按类型查询,查找所有类型为sing,并且歌名中带有爱,并且歌手姓杨的:
返回结果:
{
"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
}
}
结果正确,和数据库中记录是匹配的。
4、总结
使用Spring Data Mongodb可以非常快速简便的对mongodb中的collection进行CRUD,大大提高了我们的开发效率,目前刚用,只是有一个简单的了解,相信它并不只有这么点功能,以后继续了解深入。