您的位置:首页 > 数据库 > Mongodb

Spring整合mongodb动态实现

2015-08-31 13:26 621 查看
Spring整合mongodb的配置文件与上一篇文章没有区别,直接看接口BaseMongoDAO:

public interface BaseMongoDAO<T> {
/**
* 通过条件查询实体(集合)
*
* @param query
*/
public List<T> find(Map<String, Object> gtMap,
Map<String, Object> ltMap, Map<String, Object> eqMap,
Map<String, Object> gteMap, Map<String, Object> lteMap,
Map<String, String> regexMap, Map<String, Object> inMap,
Map<String, Object> neMap) ;

/**
* 通过一定的条件查询一个实体
*
* @param query
* @return
*/
public T findOne(Map<String, Object> gtMap,
Map<String, Object> ltMap, Map<String, Object> eqMap,
Map<String, Object> gteMap, Map<String, Object> lteMap,
Map<String, String> regexMap, Map<String, Object> inMap,
Map<String, Object> neMap) ;

/**
* 通过条件查询更新数据
*
* @param query
* @param update
* @return
*/
public void update(Map<String, Object> gtMap,
Map<String, Object> ltMap, Map<String, Object> eqMap,
Map<String, Object> gteMap, Map<String, Object> lteMap,
Map<String, String> regexMap, Map<String, Object> inMap,
Map<String, Object> neMap, Map<String, Object> params) ;

/**
* 保存一个对象到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 List<T> findList(int skip, int limit);

/**
* 求数据总和
* @param query
* @return
*/
public long count(Map<String, Object> gtMap,
Map<String, Object> ltMap, Map<String, Object> eqMap,
Map<String, Object> gteMap, Map<String, Object> lteMap,
Map<String, String> regexMap, Map<String, Object> inMap,
Map<String, Object> neMap);
}


然后是接口的实现类BaseMongoDAOImpl:

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

@Resource
private MongoTemplate mongoTemplate;

@Override
public List<T> find(Map<String, Object> gtMap,
Map<String, Object> ltMap, Map<String, Object> eqMap,
Map<String, Object> gteMap, Map<String, Object> lteMap,
Map<String, String> regexMap, Map<String, Object> inMap,
Map<String, Object> neMap) {
Criteria c = this.createCriteria(gtMap, ltMap, eqMap, gteMap, lteMap, regexMap, inMap, neMap);
Query q = this.createQuery(c);
return mongoTemplate.find(q, this.getEntityClass());
}

@Override
public T findOne(Map<String, Object> gtMap,
Map<String, Object> ltMap, Map<String, Object> eqMap,
Map<String, Object> gteMap, Map<String, Object> lteMap,
Map<String, String> regexMap, Map<String, Object> inMap,
Map<String, Object> neMap) {
Criteria c = this.createCriteria(gtMap, ltMap, eqMap, gteMap, lteMap, regexMap, inMap, neMap);
Query q = this.createQuery(c);
return mongoTemplate.findOne(q, this.getEntityClass());
}

@Override
public void update(Map<String, Object> gtMap,
Map<String, Object> ltMap, Map<String, Object> eqMap,
Map<String, Object> gteMap, Map<String, Object> lteMap,
Map<String, String> regexMap, Map<String, Object> inMap,
Map<String, Object> neMap, Map<String, Object> params) {
Criteria c = this.createCriteria(gtMap, ltMap, eqMap, gteMap, lteMap, regexMap, inMap, neMap);
Query q = this.createQuery(c);
Set<String> _set = null;
if (params != null && params.size() > 0) {
_set = params.keySet();
}
Update update = new Update().set(_set.toString(), params.get(_set));
mongoTemplate.findAndModify(q, 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 long count(Map<String, Object> gtMap,
Map<String, Object> ltMap, Map<String, Object> eqMap,
Map<String, Object> gteMap, Map<String, Object> lteMap,
Map<String, String> regexMap, Map<String, Object> inMap,
Map<String, Object> neMap) {
Criteria c = this.createCriteria(gtMap, ltMap, eqMap, gteMap, lteMap, regexMap, inMap, neMap);
Query q = this.createQuery(c);
return mongoTemplate.count(q, this.getEntityClass());
}

@Override
public List<T> findList(int skip, int limit) {
Query query = new Query();
query.with(new Sort(new Order(Direction.ASC, "_id")));
query.skip(skip).limit(limit);
return this.mongoTemplate.find(query, this.getEntityClass());
}

private Class<T> getEntityClass(){
return ReflectionUtils.getSuperClassGenricType(getClass());
}
//生成查询条件
public Criteria createCriteria(Map<String, Object> gtMap,
Map<String, Object> ltMap, Map<String, Object> eqMap,
Map<String, Object> gteMap, Map<String, Object> lteMap,
Map<String, String> regexMap, Map<String, Object> inMap,
Map<String, Object> neMap) {
Criteria c = new Criteria();
List<Criteria> listC= new ArrayList<Criteria>();
Set<String> _set = null;
if (gtMap != null && gtMap.size() > 0) {
_set = gtMap.keySet();
for (String _s : _set) {
listC.add( Criteria.where(_s).gt(gtMap.get(_s)));
}
}
if (ltMap != null && ltMap.size() > 0) {
_set = ltMap.keySet();
for (String _s : _set) {
listC.add(  Criteria.where(_s).lt(ltMap.get(_s)));
}
}
if (eqMap != null && eqMap.size() > 0) {
_set = eqMap.keySet();
for (String _s : _set) {
listC.add(  Criteria.where(_s).is(eqMap.get(_s)));
}
}
if (gteMap != null && gteMap.size() > 0) {
_set = gteMap.keySet();
for (String _s : _set) {
listC.add( Criteria.where(_s).gte(gteMap.get(_s)));
}
}
if (lteMap != null && lteMap.size() > 0) {
_set = lteMap.keySet();
for (String _s : _set) {
listC.add(  Criteria.where(_s).lte(lteMap.get(_s)));
}
}

if (regexMap != null && regexMap.size() > 0) {
_set = regexMap.keySet();
for (String _s : _set) {
listC.add(  Criteria.where(_s).regex(regexMap.get(_s)));
}
}

if (inMap != null && inMap.size() > 0) {
_set = inMap.keySet();
for (String _s : _set) {
listC.add(  Criteria.where(_s).in(inMap.get(_s)));
}
}
if (neMap != null && neMap.size() > 0) {
_set = neMap.keySet();
for (String _s : _set) {
listC.add( Criteria.where(_s).ne(neMap.get(_s)));
}
}
if(listC.size() > 0){
Criteria [] cs = new Criteria[listC.size()];
c.andOperator(listC.toArray(cs));
}
return c;
}

public Query createQuery(Criteria c) {
Query query = new Query(c);
return query;
}
}


其中主要的区别是利用反射获取泛型的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);
}
}


这样就可以动态的调用方法做CRUD操作,但是方法中传的参数Map中的键值需对应实体类中的属性名称,每次CRUD操作都需要用到反射获取泛型的class类型,对性能有影响。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  mongodb