spring集成mongodb封装的简单的CRUD


1、什么是mongodb

MongoDB是一个基于分布式文件存储的数据库。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。

        MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。他支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。Mongo最大的特点是他支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引


2、和Spring的集成

 最近公司的项目有用到mongodb,主要用于存储日志记录,所以研究了下它和spring的集成,并且做了个简单的CRUD的封装,首先用到的包是:

        spring-3.1.x以上的相关包(必须是3.1.x以上,否则集成之后运行会报错)

        spring-data-mongodb-1.3.0.M1.jar

        先看配置文件(spring-mongodb.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">    
     
  <mongo:db-factory id="mongoDbFactory"  
                  host="${mongo.host}"  
                  port="${mongo.port}"  
                  dbname="${mongo.dbname}"  
                  username="${mongo.username}"  
                  password="${database.password}"/>    
  <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">    
    <constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/>    
    </bean>  
 </beans>

 其中:host为mongodb服务器地址,port为端口号,dbname为数据库名,username为mongodb用户名,password为mongodb密码,好了,全部配置就在这里。


        接下来就是CRUD封装类

package cn.sunsharp.alibaba.core.mongo;  
  
import java.util.List;  
  
import org.springframework.data.mongodb.core.query.Query;  
import org.springframework.data.mongodb.core.query.Update;  
  
import cn.sunsharp.alibaba.core.Page;  
  
public interface BaseMongoDAO<T> {  
  
    /** 
     * 通过条件查询实体(集合) 
     *  
     * @param query 
     */  
    public List<T> find(Query query) ;  
  
    /** 
     * 通过一定的条件查询一个实体 
     *  
     * @param query 
     * @return 
     */  
    public T findOne(Query query) ;  
  
    /** 
     * 通过条件查询更新数据 
     *  
     * @param query 
     * @param update 
     * @return 
     */  
    public void update(Query query, Update update) ;  
  
    /** 
     * 保存一个对象到mongodb 
     *  
     * @param entity 
     * @return 
     */  
    public T save(T entity) ;  
  
    /** 
     * 通过ID获取记录 
     *  
     * @param id 
     * @return 
     */  
    public T findById(String id) ;  
  
    /** 
     * 通过ID获取记录,并且指定了集合名(表的意思) 
     *  
     * @param id 
     * @param collectionName 
     *            集合名 
     * @return 
     */  
    public T findById(String id, String collectionName) ;  
      
    /** 
     * 分页查询 
     * @param page 
     * @param query 
     * @return 
     */  
    public Page<T> findPage(Page<T> page,Query query);  
      
    /** 
     * 求数据总和 
     * @param query 
     * @return 
     */  
    public long count(Query query);  
      
}

实现:


package cn.sunsharp.alibaba.core.mongo.impl;

import java.util.List;

import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

import cn.sunsharp.alibaba.core.Page;
import cn.sunsharp.alibaba.core.ReflectionUtils;
import cn.sunsharp.alibaba.core.mongo.BaseMongoDAO;

public abstract class BaseMongoDAOImpl<T> implements BaseMongoDAO<T>{

	private static final int DEFAULT_SKIP = 0;
	private static final int DEFAULT_LIMIT = 200;
	
	/**
	 * spring mongodb 集成操作类 
	 */
	protected MongoTemplate mongoTemplate;

	@Override
	public List<T> find(Query query) {
		return mongoTemplate.find(query, this.getEntityClass());
	}

	@Override
	public T findOne(Query query) {
		return mongoTemplate.findOne(query, this.getEntityClass());
	}

	@Override
	public void update(Query query, Update update) {
		mongoTemplate.findAndModify(query, update, this.getEntityClass());
	}

	@Override
	public T save(T entity) {
		mongoTemplate.insert(entity);
		return entity;
	}

	@Override
	public T findById(String id) {
		return mongoTemplate.findById(id, this.getEntityClass());
	}

	@Override
	public T findById(String id, String collectionName) {
		return mongoTemplate.findById(id, this.getEntityClass(), collectionName);
	}
	
	@Override
	public Page<T> findPage(Page<T> page,Query query){
		long count = this.count(query);
		page.setTotal(count);
		int pageNumber = page.getPageNumber();
		int pageSize = page.getPageSize();
		query.skip((pageNumber - 1) * pageSize).limit(pageSize);
		List<T> rows = this.find(query);
		page.setRows(rows);
		return page;
	}
	
	@Override
	public long count(Query query){
		return mongoTemplate.count(query, this.getEntityClass());
	}
	

	/**
	 * 获取需要操作的实体类class
	 * 
	 * @return
	 */
	private Class<T> getEntityClass(){
		return ReflectionUtils.getSuperClassGenricType(getClass());
	}

	/**
	 * 注入mongodbTemplate
	 * 
	 * @param mongoTemplate
	 */
	protected abstract void setMongoTemplate(MongoTemplate mongoTemplate);

}


介于很多童鞋都在问ReflectionUtils类,这里附上


package com.yingchao.kgou.core;  
  
import java.lang.reflect.Field;  
import java.lang.reflect.InvocationTargetException;  
import java.lang.reflect.Method;  
import java.lang.reflect.ParameterizedType;  
import java.lang.reflect.Type;  
  
import org.apache.commons.lang.StringUtils;  
import org.slf4j.Logger;  
import org.slf4j.LoggerFactory;  
import org.springframework.util.Assert;  
  
/** 
 * 反射工具类. 
 *  
 * 提供访问私有变量,获取泛型类型Class, 提取集合中元素的属性, 转换字符串到对象等Util函数. 
 *  
 */  
public class ReflectionUtils {  
  
    private static Logger logger = LoggerFactory.getLogger(ReflectionUtils.class);  
  
    /** 
     * 调用Getter方法. 
     */  
    public static Object invokeGetterMethod(Object obj, String propertyName) {  
        String getterMethodName = "get" + StringUtils.capitalize(propertyName);  
        return invokeMethod(obj, getterMethodName, new Class[] {}, new Object[] {});  
    }  
  
    /** 
     * 调用Setter方法.使用value的Class来查找Setter方法. 
     */  
    public static void invokeSetterMethod(Object obj, String propertyName, Object value) {  
        invokeSetterMethod(obj, propertyName, value, null);  
    }  
  
    /** 
     * 调用Setter方法. 
     *  
     * @param propertyType 用于查找Setter方法,为空时使用value的Class替代. 
     */  
    public static void invokeSetterMethod(Object obj, String propertyName, Object value, Class<?> propertyType) {  
        Class<?> type = propertyType != null ? propertyType : value.getClass();  
        String setterMethodName = "set" + StringUtils.capitalize(propertyName);  
        invokeMethod(obj, setterMethodName, new Class[] { type }, new Object[] { value });  
    }  
  
    /** 
     * 直接读取对象属性值, 无视private/protected修饰符, 不经过getter函数. 
     */  
    public static Object getFieldValue(final Object obj, final String fieldName) {  
        Field field = getAccessibleField(obj, fieldName);  
  
        if (field == null) {  
            throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + obj + "]");  
        }  
  
        Object result = null;  
        try {  
            result = field.get(obj);  
        } catch (IllegalAccessException e) {  
            logger.error("不可能抛出的异常{}", e.getMessage());  
        }  
        return result;  
    }  
  
    /** 
     * 直接设置对象属性值, 无视private/protected修饰符, 不经过setter函数. 
     */  
    public static void setFieldValue(final Object obj, final String fieldName, final Object value) {  
        Field field = getAccessibleField(obj, fieldName);  
  
        if (field == null) {  
            throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + obj + "]");  
        }  
  
        try {  
            field.set(obj, value);  
        } catch (IllegalAccessException e) {  
            logger.error("不可能抛出的异常:{}", e.getMessage());  
        }  
    }  
  
    /** 
     * 循环向上转型, 获取对象的DeclaredField,   并强制设置为可访问. 
     *  
     * 如向上转型到Object仍无法找到, 返回null. 
     */  
    public static Field getAccessibleField(final Object obj, final String fieldName) {  
        Assert.notNull(obj, "object不能为空");  
        Assert.hasText(fieldName, "fieldName");  
        for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) {  
            try {  
                Field field = superClass.getDeclaredField(fieldName);  
                field.setAccessible(true);  
                return field;  
            } catch (NoSuchFieldException e) {//NOSONAR  
                // Field不在当前类定义,继续向上转型  
            }  
        }  
        return null;  
    }  
  
    /** 
     * 直接调用对象方法, 无视private/protected修饰符. 
     * 用于一次性调用的情况. 
     */  
    public static Object invokeMethod(final Object obj, final String methodName, final Class<?>[] parameterTypes,  
            final Object[] args) {  
        Method method = getAccessibleMethod(obj, methodName, parameterTypes);  
        if (method == null) {  
            throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + obj + "]");  
        }  
  
        try {  
            return method.invoke(obj, args);  
        } catch (Exception e) {  
            throw convertReflectionExceptionToUnchecked(e);  
        }  
    }  
  
    /** 
     * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问. 
     * 如向上转型到Object仍无法找到, 返回null. 
     *  
     * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args) 
     */  
    public static Method getAccessibleMethod(final Object obj, final String methodName,  
            final Class<?>... parameterTypes) {  
        Assert.notNull(obj, "object不能为空");  
  
        for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) {  
            try {  
                Method method = superClass.getDeclaredMethod(methodName, parameterTypes);  
  
                method.setAccessible(true);  
  
                return method;  
  
            } catch (NoSuchMethodException e) {//NOSONAR  
                // Method不在当前类定义,继续向上转型  
            }  
        }  
        return null;  
    }  
  
    /** 
     * 通过反射, 获得Class定义中声明的父类的泛型参数的类型. 
     * 如无法找到, 返回Object.class. 
     * eg. 
     * public UserDao extends HibernateDao<User> 
     * 
     * @param clazz The class to introspect 
     * @return the first generic declaration, or Object.class if cannot be determined 
     */  
    @SuppressWarnings({ "unchecked", "rawtypes" })  
    public static <T> Class<T> getSuperClassGenricType(final Class clazz) {  
        return getSuperClassGenricType(clazz, 0);  
    }  
  
    /** 
     * 通过反射, 获得Class定义中声明的父类的泛型参数的类型. 
     * 如无法找到, 返回Object.class. 
     *  
     * 如public UserDao extends HibernateDao<User,Long> 
     * 
     * @param clazz clazz The class to introspect 
     * @param index the Index of the generic ddeclaration,start from 0. 
     * @return the index generic declaration, or Object.class if cannot be determined 
     */  
    @SuppressWarnings("rawtypes")  
    public static Class getSuperClassGenricType(final Class clazz, final int index) {  
  
        Type genType = clazz.getGenericSuperclass();  
  
        if (!(genType instanceof ParameterizedType)) {  
            logger.warn(clazz.getSimpleName() + "'s superclass not ParameterizedType");  
            return Object.class;  
        }  
  
        Type[] params = ((ParameterizedType) genType).getActualTypeArguments();  
  
        if (index >= params.length || index < 0) {  
            logger.warn("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: "  
                    + params.length);  
            return Object.class;  
        }  
        if (!(params[index] instanceof Class)) {  
            logger.warn(clazz.getSimpleName() + " not set the actual class on superclass generic parameter");  
            return Object.class;  
        }  
  
        return (Class) params[index];  
    }  
  
    /** 
     * 将反射时的checked exception转换为unchecked exception. 
     */  
    public static RuntimeException convertReflectionExceptionToUnchecked(Exception e) {  
        if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException  
                || e instanceof NoSuchMethodException) {  
            return new IllegalArgumentException("Reflection Exception.", e);  
        } else if (e instanceof InvocationTargetException) {  
            return new RuntimeException("Reflection Exception.", ((InvocationTargetException) e).getTargetException());  
        } else if (e instanceof RuntimeException) {  
            return (RuntimeException) e;  
        }  
        return new RuntimeException("Unexpected Checked Exception.", e);  
    }  
}

这样,就完成了spring和mongodb的集成,其实很简单的。测试话就直接调用相关方法就可以了。。。

注:本文转载自csdn,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除。
上一篇 下一篇

分享

热门文章