`
liuluo129
  • 浏览: 116536 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

使用Spring-data-mongodb构建通用的MongoDB DAO

阅读更多

和关系型数据库类似,在使用MongoDB的时候最主要还是CRUD,而Spring-data-mongodb封装了MongoTemplate类,可以方便的进行相应的操作。

首先,配置spring

 

<?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:mongo="http://www.springframework.org/schema/data/mongo"
	xsi:schemaLocation="http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo-1.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
	<!-- Default bean name is 'mongo' -->
	<mongo:mongo host="127.0.0.1" port="27017" />
	<mongo:db-factory dbname="database" mongo-ref="mongo" />

	<!-- 扫描注解Bean -->
	<context:component-scan base-package="com.study.mongodb.**.*"> 
		<context:exclude-filter type="annotation"
			
	<bean id="mongoTemplate" 
class="org.springframework.data.mongodb.core.MongoTemplate">
		<constructor-arg name="mongoDbFactory" 
  ref="mongoDbFactory" />
	</bean>
</beans>

 在关系型数据应用程序中,一般都会用到ORM框架,而Spring-data-mongodb本身就已经实现对象到数据的映射。而封装的QueryUpdate类用来做查询和更新已经非常方便了。但是我们还是需要把实体Bean转换成Query实例。本着将懒惰进行到底的原则,这点也最好不要。

 

对于查询,一般根据实体bean的某些属性进行查询,最主要的查询有等于,likein类型。创建一个注解QueryField,代表要查询的字段

 

/**
 * <p>
 * 用于实体Bean的属性上的注解,注解有两个属性可以设置,type表示查询类似,默认为equals<br/>
 * attribute表示要查询的属性,默认为空串,在使用时如果为空串,则默认为实体Bean字段的名称
 * </p>
 *
 * @author: <a href="mailto:chuanli@sohu-inc.com">chuanli</a>
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface QueryField {
    QueryType type() default QueryType.EQUALS;
    String attribute() default "";
}

 默认使用相等。

 

QueryType是个枚举类型,表示查询类型

 

/**
 * <p>
 * 查询类型的媒介类<br/>
 * 目前有支持三种类型:<br/>
 * 1. equals:相等
 * 2. like:mongodb的like查询
 * 3. in:用于列表的in类型查询
 * </p>
 *
 * @author: <a href="mailto:chuanli@sohu-inc.com">chuanli</a>
 */
public enum QueryType {
    EQUALS {
        @Override
        public Criteria buildCriteria(QueryField queryFieldAnnotation, Field field, Object value) {
            if (check(queryFieldAnnotation, field, value)) {
                String queryField = getQueryFieldName(queryFieldAnnotation, field);
                return Criteria.where(queryField).is(value.toString());
            }
            return new Criteria();
        }
    },
    LIKE {
        @Override
        public Criteria buildCriteria(QueryField queryFieldAnnotation, Field field, Object value) {
            if (check(queryFieldAnnotation, field, value)) {
                String queryField = getQueryFieldName(queryFieldAnnotation, field);
                return Criteria.where(queryField).regex(value.toString());
            }
            return new Criteria();
        }
    },
    IN {
        @Override
        public Criteria buildCriteria(QueryField queryFieldAnnotation, Field field, Object value) {
            if (check(queryFieldAnnotation, field, value)) {
                if (value instanceof List) {
                    String queryField = getQueryFieldName(queryFieldAnnotation, field);
                    // 此处必须转型为List,否则会在in外面多一层[]
                    return Criteria.where(queryField).in((List<?>)value);
                }
            }
            return new Criteria();
        }
    };

    private static boolean check(QueryField queryField, Field field, Object value) {
        return !(queryField == null || field == null || value == null);
    }

    public abstract Criteria buildCriteria(QueryField queryFieldAnnotation, Field field, Object value);

    /**
     * 如果实体bean的字段上QueryField注解没有设置attribute属性时,默认为该字段的名称
     *
     * @param queryFieldAnnotation
     * @param field
     * @return
     */
    private static String getQueryFieldName(QueryField queryField, Field field) {
        String queryFieldValue = queryField.attribute();
        if (!StringUtils.hasText(queryFieldValue)) {
            queryFieldValue = field.getName();
        }
        return queryFieldValue;
    }
}

 这样当创建一个实体类时,可以为相应的字段添加注解即可,比如Article类:

 

public class Article {
    @QueryField
	private String id;

    @QueryField
	private String title;

    @QueryField(type = QueryType.LIKE, attribute = "content")
	private String content;

    @QueryField(type = QueryType.IN, attribute = "title")
  private List<String> queryTitles;
}

 这样一个实例可通过下面方法转换成一个Query实例

 

private Query buildBaseQuery(T t) {
        Query query = new Query();

	    Field[] fields = t.getClass().getDeclaredFields();
	    for (Field field : fields) {
	        field.setAccessible(true);
	        try {
                Object value = field.get(t);
                if (value != null) {
                    QueryField queryField = field.getAnnotation(QueryField.class);
                    if (queryField != null) {
                        query.addCriteria(queryField.type().buildCriteria(queryField, field, value));
                    }
                }
            } catch (Exception e) {
                // should not happend            
	    }
        return query;
   }

  增删改查的基本DAO如下:

 

public abstract class MongodbBaseDao<T>{

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

	//保存一个对象到mongodb
	public T save(T bean) {
	    mongoTemplate.save(bean);
	    return bean;
	}

	// 根据id删除对象
	public void deleteById(T t) {
	    mongoTemplate.remove(t);
	}

	// 根据对象的属性删除
	public void deleteByCondition(T t) {
	    Query query = buildBaseQuery(t);
	    mongoTemplate.remove(query, getEntityClass());
	}

    // 通过条件查询更新数据
	public void update(Query query, Update update) {
	    mongoTemplate.updateMulti(query, update, this.getEntityClass());
	}

	// 根据id进行更新
    public void updateById(String id, T t) {
        Query query = new Query();
        query.addCriteria(Criteria.where("id").is(id));
        Update update = buildBaseUpdate(t);
        update(query, update);
    }

	// 通过条件查询实体(集合)
	public List<T> find(Query query) {
		return mongoTemplate.find(query, this.getEntityClass());
	}

	public List<T> findByCondition(T t) {
	    Query query = buildBaseQuery(t);
	    return mongoTemplate.find(query, getEntityClass());
	}

    // 通过一定的条件查询一个实体
    public T findOne(Query query) {
        return mongoTemplate.findOne(query, this.getEntityClass());
    }


    // 通过ID获取记录
    public T get(String id) {
        return mongoTemplate.findById(id, this.getEntityClass());
    }

    // 通过ID获取记录,并且指定了集合名(表的意思)
    public T get(String id, String collectionName) {
        return mongoTemplate.findById(id, this.getEntityClass(), collectionName);
    }

    // 根据vo构建查询条件Query
    private Query buildBaseQuery(T t) {
        Query query = new Query();

	    Field[] fields = t.getClass().getDeclaredFields();
	    for (Field field : fields) {
	        field.setAccessible(true);
	        try {
                Object value = field.get(t);
                if (value != null) {
                    QueryField queryField = field.getAnnotation(QueryField.class);
                    if (queryField != null) {
                        query.addCriteria(queryField.type().buildCriteria(queryField, field, value));
                    }
                }
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
	    }
        return query;
    }

    private Update buildBaseUpdate(T t) {
        Update update = new Update();

        Field[] fields = t.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            try {
                Object value = field.get(t);
                if (value != null) {
                   update.set(field.getName(), value);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return update;
    }

	// 获取需要操作的实体类class
	@SuppressWarnings("unchecked")
    protected Class<T> getEntityClass() {
	    return ((Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]);
	}

    public MongoTemplate getMongoTemplate() {
        return mongoTemplate;
    }
}

 这样基本的CRUD就写好了,虽然一些复杂的查询和更新还得自己构造QueryUpdate,但是大部分情况足以应付了。

 

 

0
3
分享到:
评论
1 楼 yueweichao0927 2016-02-27  
return Criteria.where(queryField).is(value.toString());  改成 return Criteria.where(queryField).is(value);   能支持Integer Long 等等不是跟好一点吗楼主

相关推荐

    Java Spring-data for mongodb

    - **Repository抽象**:Spring-data-mongodb通过Repository接口提供了一套强大的CRUD操作,开发者无需编写繁琐的DAO代码。 - **Querydsl支持**:支持Querydsl,提供类型安全的查询方式,增强了查询的可读性和维护...

    Spring3+Spring-data-mongodb1.5.6示例

    7. **Repository接口**: Spring Data MongoDB的Repository接口允许开发者定义特定于领域的查询方法,而无需编写实际的DAO层代码。例如,`findAll()`、`findById()`等。 8. **查询方法命名规则**: Spring Data ...

    spring mongodb用到的jar包spring-date-mongodb1.4.2.zip

    这个压缩包`spring-date-mongodb1.4.2.zip`包含了两个核心的JAR文件:`spring-data-mongodb-1.4.2.RELEASE.jar`和`spring-data-commons-1.7.2.RELEASE.jar`,它们是Spring Data MongoDB项目的关键组成部分。...

    spring-data-commons-1.13.0.RELEAS.zip

    Spring Data Commons是Spring框架的一个重要组成部分,它为Spring Data项目提供了一套通用的基础设施,简化了与各种数据存储进行交互的过程。这个1.13.0.RELEASE版本是该模块的一个稳定版本,包含了对多种数据访问...

    springboot整合mongodb+redis+mybatis+mysql

    SpringBoot 是一个由 Pivotal 团队开发的框架,它简化了在 Spring 框架上构建应用程序的过程。这个项目旨在使初始搭建以及开发新 Spring 应用程序变得更加简单,通过内嵌的 Tomcat 容器,可以快速运行一个 Java 项目...

    spring-mongo-data

    MongoDB与Spring Data的集成允许开发者使用熟悉的Spring编程模型,无需编写大量的DAO(数据访问对象)层代码,就能方便地操作MongoDB数据库。这个框架提供了诸如CRUD操作、聚合、索引管理等常见的数据库功能,同时...

    spring Data 整合jar

    压缩包中的“SpringData”可能就是包含了这些依赖的文件夹,里面可能有`.jar`文件或者`.pom.xml`文件,用于构建工具导入。 集成Spring Data到Spring应用中,还需要配置相关的Bean,如DataSource、...

    spring-data-document-1.0.0.M4

    Spring Data Document模块使得与MongoDB的交互变得更为简单,它提供了强大的Repository抽象,允许开发者通过简单的接口定义来执行CRUD操作,无需编写繁琐的DAO层代码。 1. **Repository抽象**: Spring Data ...

    spring mvc+spring data+mongodb实例1

    在本实例中,我们将探讨如何使用Spring MVC、Spring Data以及MongoDB来构建一个实际的应用程序。Spring MVC是Spring框架的一部分,用于构建Web应用程序,而Spring Data则是Spring项目下的一个模块,它简化了与各种...

    spring-mongodb-jars

    综上所述,"spring-mongodb-jars"这个主题涵盖了大量的技术细节,包括Spring Data MongoDB的使用、对象映射、Repository接口、查询构造、事务管理、索引创建、聚合操作,以及数据库连接配置等。了解和掌握这些知识点...

    Java_使用Spring Data为JPA MongoDB Neo4j Redis的例子.zip

    通过使用Spring Data JPA,开发者可以很容易地创建CRUD(创建、读取、更新、删除)操作,而无需编写大量的DAO(Data Access Object)代码。它支持自动查询构造,包括基于方法名的简单查询和通过JPA Repository接口...

    springboot+spring-data-jpa maven项目

    - `@Repository`:在 Dao 类上使用,表明这是一个数据访问对象,Spring Data JPA 会自动处理其中的方法,如 CRUD 操作。 - `@RepositoryDefinition`:用于自定义 Dao 层的通用方法,例如分页和动态查询。 - `@...

    Spring Data MongoDB中文文档

    Spring Data MongoDB 是一个项目,它将 Spring 框架的核心概念应用于使用 MongoDB 文档样式数据存储的解决方案开发中。该项目提供了一个“模板”作为存储和查询文档的高级抽象层,其设计思想与 Spring Framework 中...

    spring-data-commons-1.3.1

    《Spring Data Commons 1.3.1:构建高效数据访问层的基石》 Spring Data Commons是Spring Data项目的核心模块,它的版本1.3.1.RELEASE是该项目在2014年发布的一个稳定版本,旨在提供一套通用的、可扩展的数据访问...

    11-Spring-Boot(十一):Spring boot中mongodb的使用.pdf

    Spring Data MongoDB 提供了Repository接口,可以直接使用`MongoRepository`,自动生成CRUD操作。创建一个接口`UserRepository`,继承`MongoRepository, Long&gt;`: ```java public interface UserRepository ...

    blanka:一个带有 Bean 验证的 Spring-Data 和 mongoDb 空白项目

    Spring-Data MongoDB 提供了与 MongoDB 集成的接口,使得开发者可以方便地在 Spring 应用中使用 MongoDB。 3. **Bean Validation**: Bean Validation 是 Java EE 规范的一部分,用于校验 Java 对象的属性值。...

    Spring-Data-MongoDB:我们的这个是关于Spring Data MongoDB 的学习和配置,其中我实现了分页和BaseDao的接口和方法,可以供大家学习和参考

    Spring-Data-MongoDB 我们的这个是关于Spring Data MongoDB 的学习和配置,其中我实现了分页和BaseDao的接口和方法,可以供大家学习和参考 ##BaseDao接口 package com.yellowcong.dao; import java.util.List; ...

    spring-data-mongo-1.0.1.RELEASE.zip

    使用Spring Data MongoDB,开发者可以轻松地实现如下功能: - **数据访问对象(DAO)抽象**:通过MongoRepository接口,可以快速实现数据访问逻辑,减少重复代码。 - **动态查询**:MongoTemplate的`query()`方法...

    Workshop-spring-boot-mongodb

    【标题】"Workshop-spring-boot-mongodb" 是一个基于Java技术栈的工作坊项目,它主要探讨了如何在Spring Boot框架下集成与使用MongoDB数据库。这个项目旨在帮助开发者掌握如何构建现代Web应用程序,利用Spring Boot...

    源码-spring+MongoDB的整合

    8. **聚合框架**:Spring Data MongoDB提供了聚合操作的支持,允许开发者构建复杂的查询管道,以分析和转换数据。 9. **索引管理**:可以通过MongoTemplate或Repository接口创建和管理MongoDB的索引,以优化查询...

Global site tag (gtag.js) - Google Analytics