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