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
學習永不止步,繼續加油~