spring整合Morphia

             在这个博客的制作中,决定使用mongodb来对文章和图片进行存储,如果纯粹使用mongodb的api来进行crud操作的话,非常麻烦,

所以在这里采用Morphia,mongodb的一个orm框架,十分好用,具体dependcy如下:

<!--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之前,我还参考了一下别人的博文的编写,其中采用许多那篇博文的代码:

       具体分为如下:

     MongoFactoryBean:

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的配置文件中,因为这里只需要这几个参数,可以说不需要

另外再写一个配置文件配置相应的参数。

           同时在datastore这个bean的编写中,我直接让这个bean扫描domain下面的所有pojo类,这样便不需要再进行相应的一个个的将相应的pojo类添加进来。

           同时在mongooptions的配置中,我去掉了几个参数,在新版本中,不需要这几个参数。

           现在进行测试:

         

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中查询相应的表:


        如此,spring与Morphia的整合便是成功的。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值