MongoDB文档数据库
1.MongoDB介绍
对于那些需要缓存而且经常需要统计、分析和查询的数据,对于Redis这样简单的NoSQL显然不是很方便,而MongoDB对于那些需要统计、按条件查询和分析的数据提供了支持,是一个最接近于关系数据库的NoSQL。
MongoDB是由C++编写的一种NoSQL,是一个基于分布式文件存储的开源数据库系统,在负载高时可以添加更多的节点以保证服务器性能。MongoDB将数据存储为一个文档,数据结构由键值(key-value)对组成。
与Redis一样,我们先引入Spring Boot关于MongoDB的starter,同时推荐引入阿里巴巴开发的fastjson开发包,方便JSON操作。代码如下(Maven):
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.46</version>
</dependency>
接下来,配置MongoDB,在application.properties属性文件中添加如下代码:
spring.data.mongodb.host=192.168.11.131 //MongoDB服务器
spring.data.mongodb.username=spring //MongoDB服务器用户名
spring.data.mongodb.password=123456
spring.data.mongodb.port=27017
spring.data.mongodb.database=springboot //数据库名称
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
logging.level.root=INFO
2.使用MongoTemplate实例
Spring Data MongoDB主要是通过MongoTemplate进行操作数据,而Spring Boot会根据配置自动生成这个对象(不需要自己创建),下面通过实例说明如何通过MongoTemplate来操作数据。
首先创建一个用户:
/**** imports ****/
// 标识为MongoDB文档
@Document
public class User implements Serializable {
private static final long serialVersionUID = -7895435231819517614L;
// MongoDB文档编号,主键
@Id
private Long id;
// 在MongoDB中使用user_name保存属性
@Field("user_name")
private String userName = null;
private String note = null;
// 角色列表
private List<Role> roles = null;
/**** setter and getter ****/
}
文档被标识为@Docunment,说明它将作为MongoDB的文档存在。注解@id则将对应的字段设为主键,使用@Field,这样属性userName与MongoDB中的user_name属性对应起来了。这里引入了角色列表,下面定义角色类:
/**** imports ****/
@Document
public class Role implements Serializable {
private static final long serialVersionUID = -6843667995895038741L;
private Long id;
@Field("role_name")
private String roleName = null;
private String note = null;
/**** setter and getter ****/
}
为了能够测试,我们新建用户测试器,代码如下:
/**** imports ****/
@Controller
@RequestMapping("/user")
public class UserController {
// 后面会给出其操作的方法
@Autowired
private UserService userService = null;
// 跳转到测试页面
@RequestMapping("/page")
public String page() {
return "user";
}
/**
* 保存(新增或者更新)用户
* @param user -- 用户
* @return 用户信息
*/
@RequestMapping("/save")
@ResponseBody
public User saveUser(@RequestBody User user) {
userService.saveUser(user);
return user;
}
/***
* 获取用户
* @param id -- 用户主键
* @return 用户信息
*/
@RequestMapping("/get")
@ResponseBody
public User getUser(Long id) {
User user = userService.getUser(id);
return user;
}
/**
* 查询用户
* @param userName --用户名称
* @param note -- 备注
* @param skip -- 跳过用户个数
* @param limit -- 限制返回用户个数
* @return
*/
@RequestMapping("/find")
@ResponseBody
public List<User> addUser(String userName, String note, Integer skip, Integer limit) {
List<User> userList = userService.findUser(userName, note, skip, limit);
return userList;
}
/**
* 更新用户部分属性
* @param id —— 用户编号
* @param userName —— 用户名称
* @param note —— 备注
* @return 更新结果
*/
@RequestMapping("/update")
@ResponseBody
public UpdateResult updateUser(Long id, String userName, String note) {
return userService.updateUser(id, userName, note);
}
/**
* 删除用户
* @param id -- 用户主键
* @return 删除结果
*/
@RequestMapping("/delete")
@ResponseBody
public DeleteResult deleteUser(Long id) {
return userService.deleteUser(id);
}
这里引入UserService接口,先暂时不讨论它的实现,这里的page方法会跳转到一个测试的JSP页面中,接下俩采用这个JSP进行一些测试:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Hello Spring Boot</title>
<script type="text/javascript"
src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script type="text/javascript">
<!--后面在此处加入JavaScript脚本-->
</script>
</head>
<body>
<h1>操作MongoDB文档</h1>
</body>
</html>
在后面的测试中,只需在对应代码处插入JS脚本就可以对后台发送HTTP的POST请求了。
3.使用MongoTemplate操作文档
上述代码使用了用户服务接口(UserService),在它的接口设计里包含了最常用的增删改查等功能,代码如下:
package com.springboot.chapter8.service;
import java.util.List;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import com.springboot.chapter8.pojo.User;
public interface UserService {
public void saveUser(User user);
public DeleteResult deleteUser(Long id);
public List<User> findUser(String userName, String note, int skip, int limit);
public UpdateResult updateUser(Long id, String userName, String note);
public User getUser(Long id);
}
下面看实现类,先来看查询,包括获取用户(getUser方法)和查询用户(findUser方法):
@Service
public class UserServiceImpl implements UserService {
// 注入MongoTemplate对象
@Autowired
private MongoTemplate mongoTmpl = null;
@Override
public User getUser(Long id) {
return mongoTmpl.findById(id, User.class);
// 如果只需要获取第一个也可以采用如下查询方法
// Criteria criteriaId = Criteria.where("id").is(id);
// Query queryId = Query.query(criteriaId);
// return mongoTmpl.findOne(queryId, User.class);
}
@Override
public List<User> findUser(String userName, String note, int skip, int limit) {
// 将用户名称和备注设置为模糊查询准则
Criteria criteria = Criteria.where("user_name").regex(userName).and("note").regex(note);
// 构建查询条件,并设置分页跳过前skip个,至多返回limit个
Query query = Query.query(criteria).limit(limit).skip(skip);
// 执行
List<User> userList = mongoTmpl.find(query, User.class);
return userList;
}
其中的Criteria criteria = Criteria.where("user_name").regex(userName).and("note").regex(note);
这里的where方法的参数设置为“userName”,这个字符串代表的是类User的属性userName;regex方法代表的是正则表达式匹配,即执行模糊查询;and方法代表连接字,代表同时满足。
启动SpringBoot应用程序后,我们可以对findUser方法进行验证,在浏览器地址输入http://localhost:8080/user/find?userName=user¬e=note&skip=5&limit=5,可以看到结果。
接着是新增用户信息,代码如下:
@Override
public void saveUser(User user) {
// 使用名称为user文档保存用户信息
mongoTmpl.save(user, "user");
// 如果文档采用类名首字符小写,则可以这样保存
// mongoTmpl.save(user);
}
为了测试这个方法的结果,我们用之前定义的JS脚本进行验证,代码如下:
unction post(user) {
var url = "./save"
$.post({
url : url,
// 此处需要告知传递参数类型为JSON,不能缺少
contentType : "application/json",
// 将JSON转化为字符串传递
data : JSON.stringify(user),
// 成功后的方法
success : function(result, status) {
if (result == null || result.id == null) {
alert("插入失败");
return;
}
}
});
}
for (var i = 1; i <= 10; i++) {
var user = {
'id' : i,
'userName' : 'user_name_' + i,
'note' : "note_" + i,
'roles' : [ {
'id' : i,
'roleName' : 'role_' + i,
'note' : 'note_' + i
}, {
'id' : i + 1,
'roleName' : 'role_' + (i + 1),
'note' : 'note_' + (i + 1)
} ]
};
post(user);
}
通过它就能够插入10条用户数据,这里可以看到用户会多一个"_class"属性,这个属性保存的是类的全限定名,通过它可以通过Java的反射机制生成对应的User。有时候我们可能需要删除或者更新,代码如下:
@Override
public DeleteResult deleteUser(Long id) {
// 构建id相等的条件
Criteria criteriaId = Criteria.where("id").is(id);
// 查询对象
Query queryId = Query.query(criteriaId);
// 删除用户
DeleteResult result = mongoTmpl.remove(queryId, User.class);
return result;
}
@Override
public UpdateResult updateUser(Long id, String userName, String note) {
// 确定要更新的对象
Criteria criteriaId = Criteria.where("id").is(id);
Query query = Query.query(criteriaId);
// 定义更新对象,后续可变化的字符串代表排除在外的属性
Update update = Update.update("user_name", userName);
update.set("note", note);
// 更新单个对象
UpdateResult result = mongoTmpl.updateFirst(query, update, User.class);
// 更新多个对象
// UpdateResult result2 = mongoTmpl.updateMulti(query, update, User.class);
return result;
}
这里与查询一样,使用主键构建了一个准则,然后使用remove方法将数据删除,执行删除后会返回一个DeleteResult对象来记录此次操作的结果。deleteCount代表删除文档的条数。
在更新方法中,定义了一个更新对象(Update),在创建它的时候,使用构造方法设置了对用户名的更新,然后使用set方法设置了note的更新,这样表明我们只是对这两个属性进行更新,其他属性并不更新。
本节代码已上传Github: https://github.com/lizeyang18/SpringBoot-2.x/tree/master/chapter8
学习永不止步,继续加油~