您的位置:首页 > 编程语言 > Java开发

spring整合Morphia

2016-01-21 08:09 519 查看
在这个博客的制作中,决定使用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的整合便是成功的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: