spring整合Morphia

             在這個博客的製做中,決定使用mongodb來對文章和圖片進行存儲,若是純粹使用mongodb的api來進行crud操做的話,很是麻煩,html

因此在這裏採用Morphia,mongodb的一個orm框架,十分好用,具體dependcy以下:java

<!--morphia-->
      <dependency>
        <groupId>org.mongodb</groupId>
        <artifactId>mongo-java-driver</artifactId>
        <version>${mongodb.version}</version>
      </dependency>
      <dependency>
        <groupId>org.mongodb.morphia</groupId>
        <artifactId>morphia</artifactId>
        <version>${morphia.version}</version>
      </dependency>
在整合Morphia以前,我還參考了一下別人的博文的編寫,其中採用許多那篇博文的代碼:

       具體分爲以下:spring

     MongoFactoryBean:mongodb

package cn.com.morphia;

import com.mongodb.*;
import org.springframework.beans.factory.config.AbstractFactoryBean;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Administrator on 2016/1/17.
 */
public class MongoFactoryBean extends AbstractFactoryBean<MongoClient> {

    /**
     * 表示服務器列表
     */
    private String[] serverStrings;

    /**
     * mongo配置對象
     */
    private MongoOptions mongoOptions;

    /**
     * 是否主從分離,默認爲false
     */
    private boolean readSecondary = false;


    public String[] getServerStrings() {
        return serverStrings;
    }

    public void setServerStrings(String[] serverStrings) {
        this.serverStrings = serverStrings;
    }

    public MongoOptions getMongoOptions() {
        return mongoOptions;
    }

    public void setMongoOptions(MongoOptions mongoOptions) {
        this.mongoOptions = mongoOptions;
    }

    public WriteConcern getWriteConcern() {
        return writeConcern;
    }

    public void setWriteConcern(WriteConcern writeConcern) {
        this.writeConcern = writeConcern;
    }

    public boolean isReadSecondary() {
        return readSecondary;
    }

    public void setReadSecondary(boolean readSecondary) {
        this.readSecondary = readSecondary;
    }

    /**
     * 設定寫策略,默認採用SAFE模式(須要拋異常)
     */
    private WriteConcern writeConcern = WriteConcern.SAFE;

    @Override
    public Class<?> getObjectType() {
        return MongoClient.class;
    }

    @Override
    protected MongoClient createInstance() throws Exception {
        MongoClient mongo = initMongo();

        //設定主從分離
        if (readSecondary) {
            mongo.setReadPreference(ReadPreference.secondaryPreferred());
        }
        //設定寫策略
        mongo.setWriteConcern(writeConcern);
        return mongo;
    }

    /**
     * 初始化mongo
     * @return
     * @throws Exception
     */
    private MongoClient initMongo() throws Exception {
        //根據條件建立mongo實例
        MongoClient mongo = null;
        List<ServerAddress> serverList = getServerList();
        mongo = new MongoClient(serverList.get(0));
        return mongo;
    }

    /**
     * 獲取mongo地址
     * @return
     */
    private List<ServerAddress> getServerList() throws Exception {
        List<ServerAddress> serverList = new ArrayList<>();
        try {
            for (String serverString: serverStrings) {
                String[] temp = serverString.split(":");
                String host = temp[0];
                if (temp.length > 2) {
                    throw new IllegalArgumentException(
                            "Invalid server address string:" + serverString
                    );
                }
                if (temp.length == 2) {
                    serverList.add(new ServerAddress(host, Integer.parseInt(temp[1])));
                } else {
                    serverList.add(new ServerAddress(host));
                }
            }
            return serverList;
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception(
                    "Error while converting serverString to ServerAddressList", e
            );
        }
    }
}
       原博文中採用的泛型是mongo,可是如今的api基本不支持這麼作了,因此我統一換成了MongoClient。

        MorphiaFactory:數據庫

package cn.com.morphia;

import org.mongodb.morphia.Morphia;
import org.springframework.beans.factory.config.AbstractFactoryBean;

/**
 * Created by Administrator on 2016/1/17.
 */
public class MorphiaFactoryBean extends AbstractFactoryBean<Morphia> {

    /**
     * 要掃描的包
     * @return
     */
    private String[] mapPackages;

    /**
     * 要映射的類
     */
    private String[] mapClasses;

    /**
     * 掃描包時,是否忽略不映射的類
     * 這裏按照Morphia的原始定義,默認設爲false
     */
    private boolean ignoreInvalidClasses;

    public String[] getMapPackages() {
        return mapPackages;
    }

    public void setMapPackages(String[] mapPackages) {
        this.mapPackages = mapPackages;
    }

    public String[] getMapClasses() {
        return mapClasses;
    }

    public void setMapClasses(String[] mapClasses) {
        this.mapClasses = mapClasses;
    }

    public boolean isIgnoreInvalidClasses() {
        return ignoreInvalidClasses;
    }

    public void setIgnoreInvalidClasses(boolean ignoreInvalidClasses) {
        this.ignoreInvalidClasses = ignoreInvalidClasses;
    }

    @Override
    public Class<?> getObjectType() {
        return Morphia.class;
    }

    @Override
    protected Morphia createInstance() throws Exception {
        Morphia morphia = new Morphia();
        if (mapPackages != null) {
            for (String packageName: mapPackages) {
                morphia.mapPackage(packageName, ignoreInvalidClasses);
            }
        }
        if (mapClasses != null) {
            for (String entityClass: mapClasses) {
                morphia.map(Class.forName(entityClass));
            }
        }
        return morphia;
    }
}
      DatastoreFactoryBean:

package cn.com.morphia;

import com.mongodb.Mongo;
import com.mongodb.MongoClient;
import org.mongodb.morphia.Datastore;
import org.mongodb.morphia.Morphia;
import org.springframework.beans.factory.config.AbstractFactoryBean;

/**
 * Created by Administrator on 2016/1/17.
 */
public class DatastoreFactoryBean extends AbstractFactoryBean<Datastore> {

    /**
     * morphia實例,最好是單例
     */
    private Morphia morphia;

    /**
     * mongo實例,最好是單例
     */
    private MongoClient mongo;

    /**
     * 數據庫名
     */
    private String dbName;

    /**
     * 用戶名,可爲空
     */
    private String username;

    /**
     * 密碼,可爲空
     */
    private String password;

    public Morphia getMorphia() {
        return morphia;
    }

    public void setMorphia(Morphia morphia) {
        this.morphia = morphia;
    }

    public MongoClient getMongo() {
        return mongo;
    }

    public void setMongo(MongoClient mongo) {
        this.mongo = mongo;
    }

    public String getDbName() {
        return dbName;
    }

    public void setDbName(String dbName) {
        this.dbName = dbName;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public boolean isToEnsureIndexes() {
        return toEnsureIndexes;
    }

    public void setToEnsureIndexes(boolean toEnsureIndexes) {
        this.toEnsureIndexes = toEnsureIndexes;
    }

    public boolean isToEnsureCaps() {
        return isToEnsureCaps;
    }

    public void setIsToEnsureCaps(boolean isToEnsureCaps) {
        this.isToEnsureCaps = isToEnsureCaps;
    }

    /**
     * 是否確認索引存在,默認false
     */
    private boolean toEnsureIndexes = false;

    /**
     * 是否確認caps存在,默認爲false
     */
    private boolean isToEnsureCaps = false;

    @Override
    public Class<?> getObjectType() {
        return Datastore.class;
    }

    @Override
    protected Datastore createInstance() throws Exception {
        //這裏的username和password能夠爲null,morphia對象會去處理
        Datastore ds = morphia.createDatastore(mongo, dbName);
        if (toEnsureIndexes) {
            ds.ensureIndexes();
        }
        if (isToEnsureCaps) {
            ds.ensureCaps();
        }
        return ds;
    }


}
    具體代碼大概就是如上,可是還有spring中配置文件的配置尚未編寫,具體以下:

     

<!-- mongoDB的配置對象 -->
	     <bean id="mongoOptions" class="com.mongodb.MongoOptions">
	         <property name="connectionsPerHost" value="10" />
	         <!-- 鏈接超時時間(毫秒),默認爲10000 -->
	         <property name="connectTimeout" value="10000" />
	         <!-- 是否建立一個finalize方法,以便在客戶端沒有關閉DBCursor的實例時,清理掉它。默認爲true -->
	         <property name="cursorFinalizerEnabled" value="true" />
	        <!-- 線程等待鏈接可用的最大時間(毫秒),默認爲120000 -->
	         <property name="maxWaitTime" value="120000" />
	         <!-- 可等待線程倍數,默認爲5.例如connectionsPerHost最大容許10個鏈接,則10*5=50個線程能夠等待,更多的線程將直接拋異常 -->
	         <property name="threadsAllowedToBlockForConnectionMultiplier" value="5" />
	        <!-- socket讀寫時超時時間(毫秒),默認爲0,不超時 -->
	         <property name="socketTimeout" value="0" />
	         <!-- 是socket鏈接在防火牆上保持活動的特性,默認爲false -->
	        <property name="socketKeepAlive" value="false" />
	         <!-- 對應全局的WriteConcern.SAFE,默認爲false -->
	         <property name="safe" value="true" />
	        <!-- 對應全局的WriteConcern中的w,默認爲0 -->
	         <property name="w" value="0" />
	         <!-- 對應全局的WriteConcern中的wtimeout,默認爲0 -->
         <property name="wtimeout" value="0" />
	         <!-- 對應全局的WriteConcern.FSYNC_SAFE,若是爲真,每次寫入要等待寫入磁盤,默認爲false -->
	         <property name="fsync" value="false" />
	         <!-- 對應全局的WriteConcern.JOURNAL_SAFE,若是爲真,每次寫入要等待日誌文件寫入磁盤,默認爲false -->
	        <property name="j" value="false" />
	    </bean>

	     <!-- 使用工廠建立mongo實例 -->
	     <bean id="mongo" class="cn.com.morphia.MongoFactoryBean">
	         <!-- mongoDB的配置對象 -->
	         <property name="mongoOptions" ref="mongoOptions"/>
	         <!-- 是否主從分離(讀取從庫),默認爲false,讀寫都在主庫 -->
	        <property name="readSecondary" value="false"/>

	         <!-- 設定寫策略,默認爲WriteConcern.SAFE,優先級高於mongoOptions中的safe -->
	         <property name="writeConcern" value="SAFE"/>

	         <!-- 設定服務器列表,默認爲localhost:27017 -->
	         <property name="serverStrings">
	             <array>
	                <value>localhost:27017</value>
	             </array>
	         </property>
	     </bean>

	    <!-- 使用工廠建立morphia實例,同時完成類映射操做 -->
	    <bean id="morphia" class="cn.com.morphia.MorphiaFactoryBean" >
	         <!-- 指定要掃描的POJO包路徑 -->
	        <property name="mapPackages">
	             <array>
	                 <value>cn.com.domain</value>
	             </array>
	         </property>
	    </bean>

	     <!-- 使用工廠建立datastore,同時完成index和caps的確認操做 -->
		<bean id="datastore" class="cn.com.morphia.DatastoreFactoryBean" >
	       <property name="morphia" ref="morphia"/>
	        <property name="mongo" ref="mongo"/>

	         <!-- collection的名稱 -->
	        <property name="dbName" value="files"/>
	         <!-- 用戶名和密碼能夠爲空 -->
	         <!-- <property name="username" value="my_username"/>
 93         <property name="password" value="my_password"/> -->

	         <!-- 是否進行index和caps的確認操做,默認爲flase -->
	        <property name="toEnsureIndexes" value="true"/>
	         <property name="isToEnsureCaps" value="true"/>
	    </bean>
             這裏我沒有再寫另一個mongodb.properties配置文件,直接將相應的參數寫到了spring的配置文件中,由於這裏只須要這幾個參數,能夠說不須要

另外再寫一個配置文件配置相應的參數。api

           同時在datastore這個bean的編寫中,我直接讓這個bean掃描domain下面的全部pojo類,這樣便不須要再進行相應的一個個的將相應的pojo類添加進來。服務器

           同時在mongooptions的配置中,我去掉了幾個參數,在新版本中,不須要這幾個參數。app

           如今進行測試:框架

         

package morphia;

import cn.com.domain.User;
import org.junit.Before;
import org.junit.Test;
import org.mongodb.morphia.Datastore;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Created by Administrator on 2016/1/19.
 */
public class TestMorphia {

    public ApplicationContext context;

    @Before
    public void init(){
        context = new ClassPathXmlApplicationContext("classpath:spring/applicationContext.xml");
    }

    @Test
    public void test() {
        Datastore datastore = (Datastore) context.getBean("datastore");
        User u = new User();
        u.setUsername("xx");
        u.setPassword("xx");
        datastore.save(u);
        System.out.println(datastore);
    }
}
       得到datastore後,進行insert操做。

      執行成功後,進mongo中查詢相應的表:dom


        如此,spring與Morphia的整合即是成功的。

相關文章
相關標籤/搜索