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

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

首先,配置spring

 



	
	
	

	
	 
		
		
	

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

 

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

 

/**
 * 

* 用于实体Bean的属性上的注解,注解有两个属性可以设置,type表示查询类似,默认为equals
* attribute表示要查询的属性,默认为空串,在使用时如果为空串,则默认为实体Bean字段的名称 *

* * @author: chuanli */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface QueryField { QueryType type() default QueryType.EQUALS; String attribute() default ""; }

 默认使用相等。

 

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

 

/**
 * 

* 查询类型的媒介类
* 目前有支持三种类型:
* 1. equals:相等 * 2. like:mongodb的like查询 * 3. in:用于列表的in类型查询 *

* * @author: chuanli */ 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 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{

    @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 find(Query query) {
		return mongoTemplate.find(query, this.getEntityClass());
	}

	public List 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 getEntityClass() {
	    return ((Class) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]);
	}

    public MongoTemplate getMongoTemplate() {
        return mongoTemplate;
    }
}

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

 

 

你可能感兴趣的:(mongodb)