MongoDB学习日记 - Spring框架集成 : spring-data-mongodb

这篇博客记录了作者集成MongoDB到Spring框架的过程,包括配置、代码实现和JUnit测试。作者提供了配置文件、基础 Dao 设计以及测试用例,特别提到了使用反射实现的统一Query和Update方法,但可能影响性能并存在潜在问题。欢迎讨论和指正。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一直想写这部分,但是由于水平太差了,一直没敢写;今天就献丑把自己的实践写一下,自己以后实际开发也可以回头看看。这里贴的代码都是自己测试真实的代码。下载地址:百度云分享(spring-mongo.rar)


配置

(注:配置大同小异,我就简单的配置了一下。)

maven pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.duanc</groupId>
  <artifactId>spring-mongo</artifactId>
  <packaging>war</packaging>
  <version>0.0.1-SNAPSHOT</version>
  <name>spring-mongo Maven Webapp</name>
  <url>http://maven.apache.org</url>

  <build>
    <finalName>spring-mongo</finalName>
    <plugins>
       <plugin>    
        <groupId> org.apache.maven.plugins</groupId>   
        <artifactId> maven-compiler-plugin</artifactId>    
        <configuration>    
            <source>1.7</source>   
            <target>1.7</target>   
        </configuration>    
        </plugin> 
        <plugin>    
            <groupId> org.apache.maven.plugins</groupId>   
            <artifactId> maven-war-plugin</artifactId>    
            <version>2.0.1</version> 
        </plugin>  
    </plugins>
  </build>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <spring.version>3.2.9.RELEASE</spring.version>
    <hibernate.version>4.0.5.Final</hibernate.version>
    <jackson.version>2.5.0</jackson.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>

    <dependency>    
      <groupId>javax.servlet</groupId>    
      <artifactId>servlet-api</artifactId>
      <version>2.5</version>
    </dependency>
    <!-- spring start -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-tx</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>${spring.version}</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-mongodb</artifactId>
        <version>1.2.0.RELEASE</version>
    </dependency>
    <!-- spring end -->

    <!-- log4j -->
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>

    <!-- jstl -->
    <dependency>  
        <groupId>javax.servlet</groupId>  
        <artifactId>jstl</artifactId>  
        <version>1.1.2</version>  
    </dependency> 

    <!-- fastjson -->  
    <dependency>  
        <groupId>com.alibaba</groupId>  
        <artifactId>fastjson</artifactId>  
        <version>1.1.41</version>  
    </dependency>  

    <dependency>  
        <groupId>commons-fileupload</groupId>  
        <artifactId>commons-fileupload</artifactId>  
        <version>1.2.2</version>  
    </dependency>  

    <!--io -->  
    <dependency>  
        <groupId>commons-io</groupId>  
        <artifactId>commons-io</artifactId>  
        <version>2.4</version>  
    </dependency>  

    <!-- <dependency>
        <groupId>org.mongodb</groupId>
        <artifactId>mongodb-driver</artifactId>
        <version>3.0.2</version>
    </dependency> -->

    <dependency>
        <groupId>org.mongodb</groupId>
        <artifactId>mongo-java-driver</artifactId>
        <version>3.0.2</version>
    </dependency>

  </dependencies>
</project>

spring-mvc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
  xmlns:tx="http://www.springframework.org/schema/tx"
  xsi:schemaLocation="http://www.springframework.org/schema/beans 
                http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
                http://www.springframework.org/schema/context 
                http://www.springframework.org/schema/context/spring-context-3.0.xsd 
                http://www.springframework.org/schema/tx   
                http://www.springframework.org/schema/tx/spring-tx-3.0.xsd  
                http://www.springframework.org/schema/mvc 
                http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

  <!--启用注解 -->
  <context:annotation-config />
  <!-- 自动扫描controller包下的所有类,使其认为spring mvc的控制器 -->
  <context:component-scan base-package="org.spring.mongo" />
  <mvc:annotation-driven />

  <!-- 启动Spring MVC的注解功能,完成请求和注解POJO的映射 -->
  <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> </bean>

  <!-- 靜態資源訪問 -->  
  <mvc:resources mapping="/resources/**" location="/resources/" /> 

  <!-- 对模型视图名称的解析,即在模型视图名称添加前后缀 -->
  <bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
    <property name="prefix" value="/jsp/" />
    <property name="suffix" value=".jsp" />
  </bean>

    <!-- 注解式事务 -->  
    <tx:annotation-driven transaction-manager="transactionManager" />  
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">  
        <property name="defaultEncoding" value="utf-8"></property>  
    </bean>  

    <import resource="classpath:/conf/spring/spring-mongo.xml"/>  
</beans>

spring-mongo.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mongo="http://www.springframework.org/schema/data/mongo" xsi:schemaLocation="http://www.springframework.org/schema/context   
          http://www.springframework.org/schema/context/spring-context-3.0.xsd   
          http://www.springframework.org/schema/data/mongo   
          http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd   
          http://www.springframework.org/schema/beans   
          http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <context:annotation-config />
    <context:component-scan base-package="org.spring.mongo" />

    <context:property-placeholder location="classpath:mongodb.properties" />

    <!-- 定义mongo对象,对应的是mongodb官方jar包中的Mongo,replica-set设置集群副本的ip地址和端口 -->
    <mongo:mongo id="mongo" replica-set="${mongo.hostport}">
        <!-- 一些连接属性的设置 -->
        <!-- <mongo:options 
         connections-per-host="${mongo.connectionsPerHost}" 
         threads-allowed-to-block-for-connection-multiplier="${mongo.threadsAllowedToBlockForConnectionMultiplier}"
         connect-timeout="${mongo.connectTimeout}" 
         max-wait-time="${mongo.maxWaitTime}" 
         socket-keep-alive="${mongo.socketKeepAlive}" 
         socket-timeout="${mongo.socketTimeout}" 
         slave-ok="${mongo.slaveOk}" 
         write-number="1" 
         write-timeout="0" 
         write-fsync="true" /> -->
         <!-- 这里我要备注下,不知道为什么 auto-connect-retry 这个属性不管我加或者不加都会报错,所以这里我干脆不设置options了  -->
    </mongo:mongo>
    <mongo:db-factory dbname="database" mongo-ref="mongo" />

    <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
        <constructor-arg ref="mongo" />
        <constructor-arg name="databaseName" value="${mongo.db}" />
    </bean>

</beans>

mongodb.properties

mongo.hostport=127.0.0.1:27017  
mongo.db=mytest
mongo.connectionsPerHost=8  
mongo.threadsAllowedToBlockForConnectionMultiplier=4  
mongo.connectTimeout=1000  
mongo.maxWaitTime=1500  
mongo.autoConnectRetry=true  
mongo.socketKeepAlive=true  
mongo.socketTimeout=1500  
mongo.slaveOk=true  

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
  http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
  <display-name>Archetype Created Web Application</display-name>

  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:conf/spring/spring-mongo.xml</param-value>
  </context-param>

  <!-- spring 监听 -->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  <!-- 字符集过滤 -->
  <filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <!-- springmvc -->
  <servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:conf/spring/spring-mvc.xml</param-value>
    </init-param>
    <load-on-startup>0</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

代码

Pagination
(注:时间限制简单设计了下,可以根据自己的想法改进)

import java.util.List;

public class Pagination {
    private int current = 1;// 当前页
    private int length = 10;// 长度
    private int skip;// 忽略个数
    private int count;// 总数
    private List<?> dataList;// 获取的List

    public int getCurrent() {
        return current;
    }
    public void setCurrent(int current) {
        if(current > 0) {
            this.current = current;
            this.skip = (current - 1) * 10;
        }
    }
    public int getLength() {
        return length;
    }
    public void setLength(int length) {
        this.length = length;
    }
    public int getSkip() {
        return skip;
    }
    public void setSkip(int skip) {
        this.skip = skip;
    }
    public List<?> getDataList() {
        return dataList;
    }
    public void setDataList(List<?> dataList) {
        this.dataList = dataList;
    }
    public int getCount() {
        return count;
    }
    public void setCount(int count) {
        this.count = count;
    }
}

BaseDao

import java.util.List;

public interface BaseDao<T, ID> {

    T findById(ID id);

    List<T> findMany(T example);

    Pagination findMany(T example, Pagination pagination);

    void insertOne(T record);

    void insertMany(List<T> records);

    boolean exists(T example);

    void deleteById(ID id);

    void deleteByExample(T example);

    void updateById(T record, ID id);

    void updataByExample(T record, T example);

}

BaseDaoImpl

  • initQuery
  • initUpdate

这连个方法我是基于java反射,写的统一方法。可以根据传入的java对象,映射属性及值,然后组装成 Query 和 Update。通过反射来做虽然方便,但是会影响速度,而且我并没有测试所有支持的数据类型,也许有些类型会有问题,需要改进。

import java.lang.reflect.Field;
import java.lang.reflect.Method;

import org.spring.mongo.model.Student;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

public abstract class BaseDaoImpl {

    protected Query initQuery(Student example) {
        Query query = new Query();
        Criteria c = new Criteria();

        Field [] fields = example.getClass().getDeclaredFields();
        for (Field field : fields) {
            String fieldName = field.getName();
            String methodName = fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1, fieldName.length());
            System.out.println(fieldName + " | " + methodName);
            try {
                Method method = example.getClass().getDeclaredMethod("get" + methodName);
                Object obj = method.invoke(example, null);
                if(obj != null) {
                    System.out.println(obj + "  type:"+ field.getGenericType());
                    if(field.getGenericType().equals(String.class)) {
                        if(fieldName.equals("id")) {
                            c.and(fieldName).is(obj);
                        } else {
                            System.out.println("is a string");
                            c.and(fieldName).regex((String)obj);
                        }
                    } else {
                        c.and(fieldName).is(obj);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        query.addCriteria(c);

        return query;
    }

    protected Update initUpdate(Object record) {
        Update update = new Update(); 

        Field [] fields = record.getClass().getDeclaredFields();
        for (Field field : fields) {
            String fieldName = field.getName();
            String methodName = fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1, fieldName.length());
            try {
                Method method = record.getClass().getDeclaredMethod("get" + methodName);
                Object obj = method.invoke(record, null);
                if(obj != null) {
                    System.out.println("obj value = " + obj);
                    update.set(fieldName, obj);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return update;
    }
}

Student

public class Student {

    private String id;
    private String name;
    private String stuCode;
    private Integer age;
    private String sex;

    private String clazzCode;

    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public String getStuCode() {
        return stuCode;
    }
    public void setStuCode(String stuCode) {
        this.stuCode = stuCode;
    }
    public String getClazzCode() {
        return clazzCode;
    }
    public void setClazzCode(String clazzCode) {
        this.clazzCode = clazzCode;
    }
}

StudentDao

import org.spring.mongo.core.BaseDao;
import org.spring.mongo.model.Student;

public interface StudentDao extends BaseDao<Student, String>{

}

StudentDaoImpl

import java.util.List;

import org.spring.mongo.core.BaseDaoImpl;
import org.spring.mongo.dao.StudentDao;
import org.spring.mongo.model.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Repository;

import com.mongodb.WriteResult;

@Repository(value = "studentDao")  
public class StudentDaoImpl extends BaseDaoImpl implements StudentDao {

    private Class<Student> entityClass =  Student.class;

    @Autowired
    @Qualifier("mongoTemplate")  
    private MongoTemplate mongoTemplate;

    @Override
    public Student findById(String id) {
        return mongoTemplate.findById(id, entityClass);
    }

    @Override
    public List<Student> findMany(Student example) {
        Query query = initQuery(example);
        return mongoTemplate.find(query, entityClass);
    }

    @Override
    public Pagination findMany(Student example, Pagination pagination) {
        Query query = initQuery(example);
        query.skip(pagination.getSkip());
        query.limit(pagination.getLength());
        List<Student> list = mongoTemplate.find(query, entityClass);
        pagination.setDataList(list);
        return pagination;
    }

    @Override
    public void insertOne(Student record) {
        mongoTemplate.insert(record);
    }

    @Override
    public void insertMany(List<Student> records) {
        mongoTemplate.insert(records, entityClass);
    }

    @Override
    public boolean exists(Student example) {
        if(findMany(example).size() > 0) {
            return true;
        }
        return false;
    }

    @Override
    public void deleteById(String id) {
        mongoTemplate.remove(new Query(Criteria.where("id").is(id)), entityClass);
    }

    @Override
    public void deleteByExample(Student example) {
        List<Student> list = findMany(example);
        for (Student student : list) {
            mongoTemplate.remove(new Query(Criteria.where("id").is(student.getId())), entityClass);
        }
    }

    @Override
    public void updateById(Student record, String id) {
        WriteResult wr = mongoTemplate.updateFirst(new Query(Criteria.where("id").is(id)), 
                initUpdate(record), entityClass);
        System.out.println(wr);
    }

    @Override
    public void updataByExample(Student record, Student example) {
        WriteResult wr = mongoTemplate.updateFirst(initQuery(example), initUpdate(record), entityClass);
        System.out.println(wr);
    }
}

Junit Test

BaseSpringTest

import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:conf/spring/spring-mvc.xml","classpath:conf/spring/spring-mongo.xml"})
public abstract class BaseSpringTest {
}

MongoTest

import java.util.List;

import org.junit.Test;
import org.spring.mongo.dao.StudentDao;
import org.spring.mongo.model.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;

public class MongoTest extends BaseSpringTest {
    @Autowired
    private StudentDao studentDao;

    @Test
    public void test() {
        /*Student s = new Student();
        s.setName("student");
        s.setAge(25);
        s.setClazzCode("1106101");
        s.setSex("m");
        s.setStuCode("1106101-25");
        studentDao.insertOne(s);*/

        /*Student s = new Student();
        s.setId("55fbdfdb555cf51ef80d6813");
        s.setName("admin");
        s.setAge(22);
        s.setSex("m");
        s.setClazzCode("1106101");
        List<Student> list = studentDao.findMany(s);

        for (Student student : list) {
            System.out.println(student.getId() + "  " + student.getStuCode() + "  " + student.getName() + "  " + student.getAge());
        }
        System.out.println("=================================");
        System.out.println(studentDao.exists(s));

        System.out.println("=================================");
        Student record = new Student();
        record.setName("system");
        record.setAge(30);
        studentDao.updateById(record, "55fbdfdb555cf51ef80d6813");*/


        /*Student s = studentDao.findById("55fbdfdb555cf51ef80d6813");
        System.out.println(s.getId() + "  " + s.getStuCode() + "  " + s.getName() + "  " + s.getAge());*/

        /*studentDao.deleteById("55fbdfdb555cf51ef80d6813");*/

        Pagination pagination = new Pagination();
        Student example = new Student();
        example.setName("student");

        List<Student> list = (List<Student>)studentDao.findMany(example, pagination).getDataList();
        for (Student student : list) {
            System.out.println(student.getId() + "  " + student.getStuCode() + "  " + student.getName() + "  " + student.getAge());
        }
    }
}

基本都是代码,实在不知道该讲什么……代码有看不懂的地方可以问我。有大神指点更好!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值