spring集成mongodb封装的简单的CRUD

来源:互联网 发布:网络信息都可信吗 编辑:程序博客网 时间:2024/06/06 01:17

1、什么是mongodb

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

  mongoDB

        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;@Overridepublic List<T> find(Query query) {return mongoTemplate.find(query, this.getEntityClass());}@Overridepublic T findOne(Query query) {return mongoTemplate.findOne(query, this.getEntityClass());}@Overridepublic void update(Query query, Update update) {mongoTemplate.findAndModify(query, update, this.getEntityClass());}@Overridepublic T save(T entity) {mongoTemplate.insert(entity);return entity;}@Overridepublic T findById(String id) {return mongoTemplate.findById(id, this.getEntityClass());}@Overridepublic T findById(String id, String collectionName) {return mongoTemplate.findById(id, this.getEntityClass(), collectionName);}@Overridepublic 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;}@Overridepublic 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的集成,其实很简单的。测试话就直接调用相关方法就可以了。。。