1. 程式人生 > >spring-data-mongodb兩種實現方式對比

spring-data-mongodb兩種實現方式對比

  之前介紹過springboot和mongodb整合,使用了spring-data-mongodb,因為springboot註解和自動化配置,我們少了很多配置,這裡介紹spring整合mongodb,使用的仍然是spring-data-mongodb,這裡需要配置一個spring-mongo.xml的配置檔案。
  spring-data-mongodb其實有兩種實現方式,一種是直接繼承MongoRepository介面,dao層的實現,預設提供了CRUD的各種方法,幾乎不用編寫任何程式碼。另一種是通過MongoTemplate來操作資料庫,這樣需要自定義dao層介面,預設沒有任何介面可以使用,但是MongoTemplate提供了操作資料庫的各種CRUD介面,因此,dao層介面需要我們再次封裝一次。


兩種方式均需要配置mongo:clientmongo:db-factorymongoTemplate類
這裡只整合spring+mongodb,因此構建的工程相對簡單:

maven工程pom.xml配置檔案:

<dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope
>
test</scope> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-mongodb</artifactId> <version>2.0.10.RELEASE</version> </dependency> <dependency> <groupId
>
org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.0.4.RELEASE</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.25</version> </dependency> </dependencies>

實體定義:

BaseEntity

package com.xxx.springmongo.entity;
import java.util.Date;
import org.springframework.data.annotation.Id;
public class BaseEntity {
	@Id
	protected String id;
	protected Date createDate;
	protected Date modifyDate;
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public Date getCreateDate() {
		return createDate;
	}
	public void setCreateDate(Date createDate) {
		this.createDate = createDate;
	}
	public Date getModifyDate() {
		return modifyDate;
	}
	public void setModifyDate(Date modifyDate) {
		this.modifyDate = modifyDate;
	}
}

User

package com.xxx.springmongo.entity;
import org.springframework.data.mongodb.core.mapping.DBRef;
import org.springframework.data.mongodb.core.mapping.Document;
@Document(collection="xx_user")
public class User extends BaseEntity{
	private String username;
	private String password;
	private String mobile;
	@DBRef
	private Role role;
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getMobile() {
		return mobile;
	}
	public void setMobile(String mobile) {
		this.mobile = mobile;
	}
	public void setRole(Role role) {
		this.role = role;
	}
	public Role getRole() {
		return role;
	}
	@Override
	public String toString() {
		return "{\"id\":"+id+",\"username\":"+username+",\"password\":"+
		password+",\"mobile\""+mobile+",\"role\":"+role+"}";
	}
}

Role

package com.xxx.springmongo.entity;
import org.springframework.data.mongodb.core.mapping.Document;
@Document(collection="xx_role")
public class Role extends BaseEntity{
	private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	@Override
	public String toString() {
		return "{\"id\":"+id+",\"name\":"+name+"}";
	}
}

實體之間的關係,使用者(User),角色(Role)均繼承BaseEntity,另外使用者有一個角色的引用。通過註解@DBRef來指定他們在資料庫中的關係。

配置檔案

mongo.properties

mongo.host=127.0.0.1
mongo.port=27017
mongo.db=springmongo

spring-mongo.xml 核心配置(需要引入spring-mongo.xsd)

<context:property-placeholder location="classpath:mongo.properties"/>
<context:component-scan base-package="com.xxx.springmongo">

</context:component-scan>
<mongo:mongo-client id="mongo-client" host="${mongo.host}" 
port="${mongo.port}">
    <mongo:client-options/>
</mongo:mongo-client>
 
<mongo:repositories base-package="com.xxx.springmongo.dao"/>

<mongo:db-factory dbname="${mongo.db}" mongo-ref="mongo-client"/>
<bean id="mongoTemplate" 
class="org.springframework.data.mongodb.core.MongoTemplate">
    <constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/>
</bean>

第一種實現方式:dao層介面繼承MongoRepository

UserDao

package com.xxx.springmongo.dao;
import org.bson.types.ObjectId;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.mongodb.repository.Query;
import com.xxx.springmongo.entity.Role;
import com.xxx.springmongo.entity.User;
public interface UserDao extends MongoRepository<User, String>{
	public User findByRole(Role role);	
	@Query(value="{'role.$id': ?0 }")
	public User findByRoleId(ObjectId id);
}

RoleDao

package com.xxx.springmongo.dao;
import org.springframework.data.mongodb.repository.MongoRepository;
import com.xxx.springmongo.entity.Role;
public interface RoleDao extends MongoRepository<Role, String>{
}

預設情況下,我們只是定義了dao層的使用者介面和角色介面,並沒有實現相關方法。UserDao中為了實現通過關聯角色查詢使用者,增加了兩個介面。
服務層介面:
RoleService

package com.xxx.springmongo.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.stereotype.Service;
import com.xxx.springmongo.dao.RoleDao;
import com.xxx.springmongo.entity.Role;
@Service
public class RoleService {
	@Autowired
	private RoleDao roleDao;
	public Role save(Role role) {
		return roleDao.save(role);
	}
	
	public Role findById(String id) {
		return roleDao.findById(id).get();
	}
	
	public Role findByName(String name) {
		Role role = new Role();
		role.setName(name);
		ExampleMatcher matcher = ExampleMatcher.matching().withMatcher("name", match->match.contains());
		Example<Role> example = Example.of(role, matcher);
		return roleDao.findOne(example).get();
	}
}

UserService

package com.xxx.springmongo.service;
import java.util.List;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.xxx.springmongo.dao.UserDao;
import com.xxx.springmongo.entity.Role;
import com.xxx.springmongo.entity.User;
@Service
public class UserService {
	@Autowired
	private UserDao userDao;	
	public User save(User user) {
		return userDao.save(user);
	}
	public User findById(String id) {
		return userDao.findById(id).get();
	}
	public List<User> findAll(){
		return userDao.findAll();
	}
	public User findByRole(Role role) {
		return userDao.findByRoleId(new ObjectId(role.getId()));
	}
}

測試類:

AppTest

package com.xxx.springmongo;
import java.util.Date;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.xxx.springmongo.entity.Role;
import com.xxx.springmongo.entity.User;
import com.xxx.springmongo.service.RoleService;
import com.xxx.springmongo.service.UserService;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:spring-mongo.xml")
public class AppTest {
	@Autowired
	private UserService userService;
	@Autowired
	private RoleService roleService;
	
	@Test
	public void save() {
		Role role = new Role();
		role.setName("superadmin");
		role.setCreateDate(new Date());
		role.setModifyDate(new Date());
		Role save = roleService.save(role);
		Assert.assertEquals("superadmin", save.getName());
	}
	
	@Test
	public void query() {
		Role role = roleService.findByName("admin");
		System.out.println(role);
		//Assert.assertEquals("admin", role.getName());
		User user = new User();
		user.setCreateDate(new Date());
		user.setUsername("admin");
		user.setPassword("admin");
		user.setMobile("15011186302");
		user.setModifyDate(new Date());
		user.setRole(role);
		User tmp = userService.save(user);
		Assert.assertEquals("admin", tmp.getUsername());
	}
	
	@Test
	public void query1() {
		Role role = roleService.findByName("admin");
		User tmp = userService.findByRole(role);
		System.out.println(tmp);
		Assert.assertEquals("admin", tmp.getUsername());
	}
}

以上測試用例只寫了新增角色,新增使用者,按照角色名查詢角色,按照角色查詢使用者。其中按照角色查詢使用者是一個關聯查詢,在MongoRepository的實現方式中有兩種實現:

  • 第一種是和普通的按照屬性查詢的方式實現。
  • 第二種是稍微有一點改變,就是模擬在mongo-shell下通過關聯屬性role欄位的$id來查詢
> db.xx_user.find({"role.$id":new ObjectId("5bdfbbc2e6c87e4f147f7fab")})
{ "_id" : ObjectId("5bdfed63e6c87e569c9f8865"), 
"username" : "admin",
"password" : "admin", 
"mobile" : "15011186302", 
"role" : DBRef("xx_role", 
ObjectId("5bdfbbc2e6c87e4f147f7fab")), 
"createDate" : ISODate("2018-11-05T07:12:35.739Z"), 
"modifyDate" : ISODate("2018-11-05T07:12:35.739Z"),
 "_class" : "com.xxx.springmongo.entity.User" }
>

第二種實現方式:通過MongoTemplate來操作資料庫

IBaseDao定義一個基礎介面

package com.xxx.springmongo.mongo.dao;
import java.io.Serializable;
import java.util.List;
import org.springframework.data.domain.Page;
public interface IBaseDao<T> {
	void save(T entity);
	void update(T entity);
	void delete(Serializable... ids);
	T find(Serializable id);
	List<T> findAll();
	List<T> findAll(String order);
	List<T> findByProp(String propName,Object value);
	List<T> findByProp(String propName,Object value,String order);
	List<T> findByProps(String[] propName,Object[] values);
	List<T> findByProps(String[] propName,Object[] values,String order);
	T uniqueByProp(String propName,Object value);
	T uniqueByProps(String[] propName,Object[] values);
	int countByCondition(String[] params,Object[] values);
}

UserDao

package com.xxx.springmongo.mongo.dao;
import com.xxx.springmongo.entity.User;
public interface UserDao extends IBaseDao<User>{
}

BaseDaoImpl

package com.xxx.springmongo.mongo.dao.impl;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.annotation.Id;

            
           

相關推薦

spring-data-mongodb實現方式對比

  之前介紹過springboot和mongodb整合,使用了spring-data-mongodb,因為springboot註解和自動化配置,我們少了很多配置,這裡介紹spring整合mongodb,使用的仍然是spring-data-mongodb,這裡需要配置一個spring-mo

spring ----> aop的實現方式

select imp ack exe readv expr gpo for public 實現1:基於xml 1 package com.rr.spring3.interf; //接口 2 3 public interface SayHello { 4 5

spring中AOP的實現方式

1.方法一:註解實現 介面類 public interface User { public void work(); } 具體實現類 public class IUser implements User { public void work() {

Spring 詳解(二)------- AOP關鍵概念以及實現方式

目錄 1. AOP 關鍵詞 2. AOP 的作用 3. AOP 的通知型別 4. 基於 xml 的配置方式 5. 基於註解的配置方式 6. 切面的優先順序 7. 重用切點表示式 8. 兩種方式的比較(摘自 spring 官方文件) 1. AOP 關鍵詞

Spring 詳解(二)------- AOP概念以及實現方式

  target:目標類,需要被代理的類。例如:ArithmeticCalculator      Joinpoint(連線點):所謂連線點是指那些可能被攔截到的方法。例如:所有的方法      PointCut 切入點:已經被增強的連線點。例如:add()      advice:通知/增強,增強

Spring Boot2 系列教程(十六)定時任務的實現方式

在 Spring + SpringMVC 環境中,一般來說,要實現定時任務,我們有兩中方案,一種是使用 Spring 自帶的定時任務處理器 @Scheduled 註解,另一種就是使用第三方框架 Quartz ,Spring Boot 源自 Spring+SpringMVC ,因此天然具備這兩個 Spring

曹工說Spring Boot原始碼(14)-- AspectJ的Load-Time-Weaving的實現方式細細講解,以及怎麼和Spring Instrumentation整合

寫在前面的話 相關背景及資源: 曹工說Spring Boot原始碼(1)-- Bean Definition到底是什麼,附spring思維導圖分享 曹工說Spring Boot原始碼(2)-- Bean Definition到底是什麼,咱們對著介面,逐個方法講解 曹工說Spring Boot原始碼(3)--

[轉]Web APi之認證(Authentication)實現方式【二】(十三)

用戶數 ted das 客戶 元素 基礎 目標 開始 net 本文轉自:http://www.cnblogs.com/CreateMyself/p/4857799.html 前言 上一節我們詳細講解了認證及其基本信息,這一節我們通過兩種不同方式來實現認證,並且分析如

多線程實現方式的區別

http [] tick 避免 main 單繼承 style 區別 tar 請解釋Thread類與Runnable接口實現多線程的區別?(請解釋多線程兩種實現方式的區別?) 1. Thread類時Runnable接口的子類,使用Runnable接口實現多線程可以避免單繼承局

JPA 派生標識符的實現方式

string column public tid man pri one embed page 方法一:@Entity@IdClass(ModuleId.class)public class Module { @Id private Integer index;

14、Fibonacci的實現方式

等於 cheng pos art log ref clas gpo tar 斐波納契數列,又稱黃金分割數列,指的是這樣一個數列:1、1、2、3、5、8、13、21、……在數學上,斐波納契數列以如下被以遞歸的方法定義:F0=0,F1=1,Fn=F(n-1)+F(n-2)(n&

Web APi之認證(Authentication)實現方式【二】(十三)

基於web 推薦 zed {0} scheme sage https 函數 ges 原文:Web APi之認證(Authentication)兩種實現方式【二】(十三)前言 上一節我們詳細講解了認證及其基本信息,這一節我們通過兩種不同方式來實現認證,並且分析如何合理的利用

spring AOP的配置方式

can 之前 top () 就是 記錄 string -s 服務   連接點(JoinPoint) ,就是spring允許你是通知(Advice)的地方,那可就真多了,基本每個方法的前、後(兩者都有也行),或拋出異常是時都可以是連接點,spring只支持方法連接點。其

Ajax的實現方式

enc () != 部分 pen clas servlet 瀏覽器 pop //ajax的jquery實現 function aclick(){//alert("測

圖形驗證碼的實現方式

ava 輸入 urn color deb rect lac prev 後臺 情形一:圖形驗證碼跟短信驗證碼一起,只需要將後臺提供的動態鏈接填到(id="img")的src中即可生成動態驗證碼。 然後,在需要請求接口的地方,只需把(id="imgCode")中用戶輸入的信息通

前端路由的實現方式

color 前端路由 his 頁面 無刷新 原理 range window 使用 什麽是路由? 路由是根據不同的 url 地址展示不同的內容或頁面 早期的路由都是後端直接根據 url 來 reload 頁面實現的,即後端控制路由。 後來頁面越來越復雜,服務器壓力越來越大,隨

題目24-多線程實現方式

類重寫 直接 解決方案 做的 子類 是否為空 缺點 多線程同步 弊端 1、多線程兩種實現方式 (1)繼承Thread 定義類繼承Thread 重寫run方法 把新線程要做的事寫在run方法中 創建線程對象 開啟新線程, 內部會自動執行run方法(2)實現Runnable

線程的實現方式

class args new pub nds runnable implement ide start 線程的兩種實現方式 (1)繼承Thread類`` /** * 繼承Thread類 * */ public class PayThread extends T

iOS活動倒計時的實現方式

ofo orm ren 年-月 ats omd string 分享 截圖 代碼地址如下:<br>http://www.demodashi.com/demo/11076.html 在做些活動界面或者限時驗證碼時, 經常會使用一些倒計時突出展現. 現提供兩種方

Brute-Force模式匹配演算法實現方式

1. public static int indexOf(String mainStr,String subString,int start) { if((mainStr.length()<subString.length()) || mainStr==null || subStr