Spring配置MongoDB及 构建通用Dao


(文章的编写虽然不至于花费很多时间,但转载请注明来源。本文参考了:http://liuluo129.iteye.com/blog/1994045,在此基础上进行了部分优化,及详细的介绍了流程)

1.首先引入Maven 依赖,如果不是用Maven管理项目,那么应该下载对应的Jar包并添加到项目lib下

 1         <dependency>
 2             <groupId>org.springframework.data</groupId>
 3             <artifactId>spring-data-mongodb</artifactId>
 4             <version>1.4.1.RELEASE</version>
 5         </dependency>
 6 
 7         <dependency>
 8             <groupId>org.mongodb</groupId>
 9             <artifactId>casbah_2.9.3</artifactId>
10             <version>2.7.0-RC2</version>
11         </dependency>

2.Spring中配置MongoDB,创建 spring-mongo.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.2.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.2.xsd">


    <!--mongoDB-->

    <context:property-placeholder location="classpath:config.properties" />
    <!-- Default bean name is 'mongo' -->
    <mongo:mongo host="${mongo.host}" port="${mongo.port}">
        <mongo:options connections-per-host="${mongo.connectionsPerHost}"
                       threads-allowed-to-block-for-connection-multiplier="${mongo.threadsAllowedToBlockForConnectionMultiplier}"
                       connect-timeout="${mongo.connectTimeout}"
                       max-wait-time="${mongo.maxWaitTime}"
                       auto-connect-retry="${mongo.autoConnectRetry}"
                       socket-keep-alive="${mongo.socketKeepAlive}"
                       socket-timeout="${mongo.socketTimeout}"
                       slave-ok="${mongo.slaveOk}"
                       write-number="1"
                       write-timeout="0"
                       write-fsync="true" />
    </mongo:mongo>

    <mongo:db-factory id="mongoDbFactory" dbname="kycloud" mongo-ref="mongo" />




    <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
        <constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
    </bean>

    <!-- 映射转换器,扫描back-package目录下的文件,根据注释,把它们作为mongodb的一个collection的映射 -->
    <!-- <mongo:mapping-converter base-package="net.xxx.mongo.**" />-->

    <!-- mongodb bean的仓库目录,会自动扫描扩展了MongoRepository接口的接口进行注入 -->
    <!--<mongo:repositories base-package="net.xxx.mongo.**"/>-->
    <context:annotation-config />
    
    

</beans>

3. config.properties 内容

#-------------- MongoDB
mongo.host=localhost
mongo.port=27017
mongo.connectionsPerHost=8
mongo.threadsAllowedToBlockForConnectionMultiplier=3
mongo.connectTimeout=3000
mongo.maxWaitTime=1500
mongo.autoConnectRetry=true
mongo.socketKeepAlive=true
mongo.socketTimeout=2000
mongo.slaveOk=true

4.将spring-mongo.xml引入到web.xml 目的当然是使Spring容器能检测并加载到容器中

    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath*:/applicationContext-mvc.xml,classpath*:/applicationContext-data-jpa.xml,classpath*:/spring-mongo.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

5.关键的部分 注解及查询套件的构建

  QueryField.java

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * type表示查询类似,默认为equals
 * attribute表示要查询的属性,默认为空串,如果为空则为字段名称
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface QueryField {
    QueryType type() default QueryType.EQUALS;
    String attribute() default "";
}

  QueryType.java

import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.util.StringUtils;

import java.lang.reflect.Field;
import java.util.List;

/**
 * 查询媒介
 * 1. equals:相等
 * 2. like:mongodb的like查询
 * 3. in:用于列表的in类型查询
 */
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 field
     * @return
     */
    private static String getQueryFieldName(QueryField queryField, Field field) {
        String queryFieldValue = queryField.attribute();
        if (!StringUtils.hasText(queryFieldValue)) {
            queryFieldValue = field.getName();
        }
        return queryFieldValue;
    }
}

 QueryField.java和QueryType.ava的编写的目的是为了公用Dao服务。注意不要引入错误的包。

 

6.公用Dao的构建

  MongoDao.java

package net.shopxx.commons.component.mongo;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

import java.util.List;


public interface MongoDao<T> {

    //保存一个对象到mongodb
    public T save(T bean);
    // 根据id删除对象
    public void deleteById(T t);

    // 根据对象的属性删除
    public void deleteByCondition(T t);

    // 通过条件查询更新数据
    public void update(Query query, Update update);

    // 根据id进行更新
    public void updateById(String id, T t);

    // 通过条件查询实体(集合)
    public List<T> find(Query query);

    public List<T> findByCondition(T t);

    // 通过一定的条件查询一个实体
    public T findOne(Query query);


    // 通过ID获取记录
    public T get(String id);

    // 通过ID获取记录,并且指定了集合名(表的意思)
    public T get(String id, String collectionName);

    public MongoTemplate getMongoTemplate();
}

实现类MongoDaoSupport.java

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.List;

public abstract  class MongoDaoSupport<T> implements MongoDao<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;
    }

}

 

7.-------------------------------正式开始使用

  >>>实体

import net.xxx.commons.component.mongo.QueryField;


public class DeviceToken  extends BaseEntity {



    @QueryField
    private Long uid;


    @QueryField
    private String token;

    @QueryField
    private String device;

    @QueryField
    private String userAgent;


    public DeviceToken(Long uid, String token, String device, String userAgent) {
        this.uid = uid;
        this.token = token;
        this.device = device;
        this.userAgent = userAgent;
    }


    public Long getUid() {
        return uid;
    }

    public void setUid(Long uid) {
        this.uid = uid;
    }

    public String getToken() {
        return token;
    }

    public void setToken(String token) {
        this.token = token;
    }

    public String getDevice() {
        return device;
    }

    public void setDevice(String device) {
        this.device = device;
    }

    public String getUserAgent() {
        return userAgent;
    }

    public void setUserAgent(String userAgent) {
        this.userAgent = userAgent;
    }
}

>>>Service

public interface DeviceTokenService extends MongoDao<DeviceToken> {
   
}

>>>ServiceImpl

@Service("deviceTokenServiceImpl")
public class DeviceTokenServiceImpl  extends MongoDaoSupport<DeviceToken> implements DeviceTokenService {

}

>>> 应用

 

 @Resource
    private DeviceTokenService deviceTokenService;  //注入到需要应用的文件


 //查询示例
 List<DeviceToken> dts=  deviceTokenService.find(new BasicQuery(new BasicDBObject("uid",uid),new BasicDBObject("userAgent",userAgent))); 




具体其他方法的使用可以扩充MongDao 和MongoDaoSupport.

 

 

 

 

 

 

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM