Spring整合MongoDb

随着数据量的不断上涨,项目需要快速处理数据成为了第一要务,对于数据统计的严格性要求不高。

MongoDb应运而生,MongoDb是典型的文档性的数据库,对于保存多层级的数据比较方便,同时MongoDb更强调用户的访问速度,采用的是若一致性,对于数据请求提供一个“大约”的数字,以求更快处理数据。

MongoDb中内置GridFs,支持大容量的存储,同时也包含了Sharding,提供了基于Range的AUTO Sharding机制。

一个集合可按照记录的范围,分为若干的段,切分到不同的shard上。配合Replica sets实现Sharding+fail-over,不同的Sharding之间支持负载均衡。

所以说mongoDb是快速处理大数据的一个选择。

Spring Data MongoDb

Spring Data其实是一个高级别的Spring Source项目,而Spring Data MongoDB仅仅是其中的一个子项目。

  1. 导入MongoDb的jar依赖

        
            org.springframework.data
            spring-data-mongodb
            ${spring.data.version}
        
  1. 创建MongoDb映射的实体类(pojo)
@Data
@Document(collection = "coll_user")
public class UserInfo implements Serializable {
 
    /** serialVersionUID */
    private static final long serialVersionUID = 1L;
 
    // 主键使用此注解
    @Id
    private String id;
 
    // 字段使用此注解
    @Field
    private String name;
 
    // 字段还可以用自定义名称
    @Field("myage")
    private int age;
 
    // 还可以生成索引
    @Indexed(name = "index_birth", direction = IndexDirection.DESCENDING)
    @Field
    private Timestamp birth;
}

类名上加@Data注解,导入依赖:lombok.Data,自动实现生成Getter,Setter,equals,hashCode,toString方法

@Document - 用于类,以表示这个类需要映射到数据库,您也可以指定映射到数据库的集合名称,上面添加了集合的名称

@Field - 用于字段,并描述字段的名称,因为它将在MongoDB BSON文档中表示,允许名称与该类的字段名不同。

@Indexed - 用于字段,表示该字段需要如何创建索引

@DBRef - 用于字段,以表示它将使用com.mongodb.DBRef进行存储。

  1. 创建Spring-mongo.xml的配置文件
    或者直接再spring配置文件中整合即可


 
    
    
 
    
    
 
    
    
 
    
    
        
            
                
            
        
    
 
    
    
        
    
 
    
 
    
        
        
    
 


主要配置了mongo连接配置,db-factory相当于sessionFactory ,mongoTemplate与数据库接口交互的主要实现类 。

mongo:options - 用于配置一些数据库连接设置信息

mongo:db-factory - 相当于Hibernate中的SessionFactory

mongoTemplate - 非常重要,整个与数据库的交互操作全是靠他,相当于Hibernate的HibernateTemplate。

  1. 使用MongoTemplate对MongoDb进行CRUD
@Autowired
protected MongoTemplate mgt;

首先注入MongoTemplate

public abstract class BaseDaoImpl implements IBaseDao {
 
    protected abstract Class getEntityClass();
 
    @Autowired
    protected MongoTemplate mgt;
 
    @Override
    public void save(T entity) {
        mgt.save(entity);
    }
 
    @Override
    public void update(T entity) {
 
        // 反向解析对象
        Map map = null;
        try {
            map = parseEntity(entity);
        } catch (Exception e) {
            e.printStackTrace();
        }
 
        // ID字段
        String idName = null;
        Object idValue = null;
 
        // 生成参数
        Update update = new Update();
        if (EmptyUtil.isNotEmpty(map)) {
            for (String key : map.keySet()) {
                if (key.indexOf("{") != -1) {
                    // 设置ID
                    idName = key.substring(key.indexOf("{") + 1, key.indexOf("}"));
                    idValue = map.get(key);
                } else {
                    update.set(key, map.get(key));
                }
            }
        }
        mgt.updateFirst(new Query().addCriteria(where(idName).is(idValue)), update, getEntityClass());
    }
 
    @Override
    public void delete(Serializable... ids) {
        if (EmptyUtil.isNotEmpty(ids)) {
            for (Serializable id : ids) {
                mgt.remove(mgt.findById(id, getEntityClass()));
            }
        }
 
    }
 
    @Override
    public T find(Serializable id) {
        return mgt.findById(id, getEntityClass());
    }
 
    @Override
    public List findAll() {
        return mgt.findAll(getEntityClass());
    }
 
    @Override
    public List findAll(String order) {
        List orderList = parseOrder(order);
        if (EmptyUtil.isEmpty(orderList)) {
            return findAll();
        }
        return mgt.find(new Query().with(new Sort(orderList)), getEntityClass());
    }
 
    @Override
    public List findByProp(String propName, Object propValue) {
        return findByProp(propName, propValue, null);
    }
 
    @Override
    public List findByProp(String propName, Object propValue, String order) {
        Query query = new Query();
        // 参数
        query.addCriteria(where(propName).is(propValue));
        // 排序
        List orderList = parseOrder(order);
        if (EmptyUtil.isNotEmpty(orderList)) {
            query.with(new Sort(orderList));
        }
        return mgt.find(query, getEntityClass());
    }
 
    @Override
    public List findByProps(String[] propName, Object[] propValue) {
        return findByProps(propName, propValue, null);
    }
 
    @Override
    public List findByProps(String[] propName, Object[] propValue, String order) {
        Query query = createQuery(propName, propValue, order);
        return mgt.find(query, getEntityClass());
    }
 
    @Override
    public T uniqueByProp(String propName, Object propValue) {
        return mgt.findOne(new Query(where(propName).is(propValue)), getEntityClass());
    }
 
    @Override
    public T uniqueByProps(String[] propName, Object[] propValue) {
        Query query = createQuery(propName, propValue, null);
        return mgt.findOne(query, getEntityClass());
    }
 
    @Override
    public PageModel pageAll(int pageNo, int pageSize) {
        return pageAll(pageNo, pageSize, null);
    }
 
    @Override
    public PageModel pageAll(int pageNo, int pageSize, String order) {
        return pageByProp(pageNo, pageSize, null, null, order);
    }
 
    @Override
    public PageModel pageByProp(int pageNo, int pageSize, String param, Object value) {
        return pageByProp(pageNo, pageSize, param, value, null);
    }
 
    @Override
    public PageModel pageByProp(int pageNo, int pageSize, String param, Object value, String order) {
        String[] params = null;
        Object[] values = null;
        if (EmptyUtil.isNotEmpty(param)) {
            params = new String[] { param };
            values = new Object[] { value };
        }
        return pageByProps(pageNo, pageSize, params, values, order);
    }
 
    @Override
    public PageModel pageByProps(int pageNo, int pageSize, String[] params, Object[] values) {
        return pageByProps(pageNo, pageSize, params, values, null);
    }
 
    @Override
    public PageModel pageByProps(int pageNo, int pageSize, String[] params, Object[] values, String order) {
        // 创建分页模型对象
        PageModel page = new PageModel<>(pageNo, pageSize);
 
        // 查询总记录数
        int count = countByCondition(params, values);
        page.setTotalCount(count);
 
        // 查询数据列表
        Query query = createQuery(params, values, order);
 
        // 设置分页信息
        query.skip(page.getFirstResult());
        query.limit(page.getPageSize());
 
        // 封装结果数据
        page.setList(mgt.find(query, getEntityClass()));
 
        return page;
    }
 
    @Override
    public int countByCondition(String[] params, Object[] values) {
        Query query = createQuery(params, values, null);
        Long count = mgt.count(query, getEntityClass());
        return count.intValue();
    }
 
    /**
     * 创建带有where条件(只支持等值)和排序的Query对象
     * 
     * @param params
     *            参数数组
     * @param values
     *            参数值数组
     * @param order
     *            排序
     * @return Query对象
     */
    protected Query createQuery(String[] params, Object[] values, String order) {
        Query query = new Query();
 
        // where 条件
        if (EmptyUtil.isNotEmpty(params) && EmptyUtil.isNotEmpty(values)) {
            for (int i = 0; i < params.length; i++) {
                query.addCriteria(where(params[i]).is(values[i]));
            }
        }
 
        // 排序
        List orderList = parseOrder(order);
        if (EmptyUtil.isNotEmpty(orderList)) {
            query.with(new Sort(orderList));
        }
 
        return query;
    }
 
    /**
     * 解析Order字符串为所需参数
     * 
     * @param order
     *            排序参数,如[id]、[id asc]、[id asc,name desc]
     * @return Order对象集合
     */
    protected List parseOrder(String order) {
        List list = null;
        if (EmptyUtil.isNotEmpty(order)) {
            list = new ArrayList();
            // 共有几组排序字段
            String[] fields = order.split(",");
            Order o = null;
            String[] item = null;
            for (int i = 0; i < fields.length; i++) {
                if (EmptyUtil.isEmpty(fields[i])) {
                    continue;
                }
                item = fields[i].split(" ");
                if (item.length == 1) {
                    o = new Order(Direction.ASC, item[0]);
                } else if (item.length == 2) {
                    o = new Order("desc".equalsIgnoreCase(item[1]) ? Direction.DESC : Direction.ASC, item[0]);
                } else {
                    throw new RuntimeException("排序字段参数解析出错");
                }
                list.add(o);
            }
        }
        return list;
    }
 
    /**
     * 将对象的字段及值反射解析为Map对象
* 这里使用Java反射机制手动解析,并且可以识别注解为主键的字段,以达到根据id进行更新实体的目的
* key:字段名称,value:字段对应的值 * * @param t * 要修改的对象 * @return Map对象,注意:id字段的key封装为“{id字段名称}”,以供后续识别 * @throws Exception */ protected Map parseEntity(T t) throws Exception { Map map = new HashMap(); /* * 解析ID */ String idName = ""; Field[] declaredFields = getEntityClass().getDeclaredFields(); for (Field field : declaredFields) { if (field.isAnnotationPresent(Id.class)) { field.setAccessible(true); map.put("{" + field.getName() + "}", field.get(t)); idName = field.getName(); break; } } /* * 解析其他属性 */ Method[] methods = getEntityClass().getDeclaredMethods(); if (EmptyUtil.isNotEmpty(methods)) { for (Method method : methods) { if (method.getName().startsWith("get") && method.getModifiers() == Modifier.PUBLIC) { String fieldName = parse2FieldName(method.getName()); if (!fieldName.equals(idName)) { map.put(fieldName, method.invoke(t)); } } } } return map; } /** * 将get方法名转换为对应的字段名称 * * @param methodName * 如:getName * @return 如:name */ private String parse2FieldName(String methodName) { String name = methodName.replace("get", ""); name = name.substring(0, 1).toLowerCase() + name.substring(1); return name; } }

你可能感兴趣的:(Spring整合MongoDb)