Morphia简介
随着互联网web2.0网站的兴起,传统的关系数据库在应付web2.0网站,特别是超大规模和高并发的SNS类型的web2.0纯动态网站已经显得力不从心,暴露了很多难以克服的问题,而非关系型的数据库则由于其本身的特点得到了非常迅速的发展。NoSQL数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑战,尤其是大数据应用难题。
Mongodb作为NoSQL数据库中的新生代表,已经被众多企业在项目中运用。Morphia是基于NoSQL的ORM框架。简化了NoSQL的持久层操作。下面来简单介绍Morphia的使用案例。
Morphia创建工厂
public class MorphiaFactoryBean extends AbstractFactoryBean<Morphia> {
/**
* 要扫描并映射的包
*/
private String[] mapPackages;
/**
* 要映射的类
*/
private String[] mapClasses;
/**
* 扫描包时,是否忽略不映射的类
* 这里按照Morphia的原始定义,默认设为false
*/
private boolean ignoreInvalidClasses;
public Class<?> getObjectType() {
return Morphia.class;
}
protected Morphia createInstance() throws Exception {
Morphia morphia = new Morphia();
if (mapPackages != null) {
for (String packageName : mapPackages) {
//我们告诉Morphia去指定的package中寻找所有标记了@Entity的类,以及所有在类中的映射元数据
morphia.mapPackage(packageName, ignoreInvalidClasses);
}
}
if (mapClasses != null) {
for (String entityClass : mapClasses) {
morphia.map(Class.forName(entityClass));
}
}
return morphia;
}
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;
}
}
Mongodb的实例工厂
public class MongoFactoryBean extends AbstractFactoryBean<Mongo> {
// 表示服务器列表(主从复制或者分片)的字符串数组
private String[] serverStrings;
// mongoDB配置对象 使用默认配置
private MongoClientOptions mongoClientOptions = new MongoClientOptions.Builder().build();
public Class<?> getObjectType() {
return Mongo.class;
}
/**
* 创建实例
* @return
* @throws Exception
*/
protected MongoClient createInstance() throws Exception {
MongoClient mongoClient = null;
//MongoCredential credential = MongoCredential.createCredential("user", "mydb", "password".toCharArray());
/*if (null != mongoClientOptions) {
mongoClient = new MongoClient(getServerList(), Arrays.asList(credential), mongoClientOptions);
} else {
mongoClient = new MongoClient(getServerList(), Arrays.asList(credential));
}*/
if(null != mongoClientOptions){
mongoClient = new MongoClient(getServerList(),mongoClientOptions);
}else{
mongoClient = new MongoClient(getServerList());
}
return mongoClient;
}
public String[] getServerStrings() {
return serverStrings;
}
public void setServerStrings(String[] serverStrings) {
this.serverStrings = serverStrings;
}
/**
* 根据服务器字符串列表,解析出服务器对象列表
* @return
* @throws Exception
* @Title: getServerList
*/
private List<ServerAddress> getServerList() throws Exception {
List<ServerAddress> serverList = new ArrayList<ServerAddress>();
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);
} else if (temp.length == 2) {
serverList.add(new ServerAddress(host, Integer.parseInt(temp[1])));
} else {
serverList.add(new ServerAddress(host));
}
}
return serverList;
} catch (Exception e) {
throw new Exception("Error while converting serverString to ServerAddressList", e);
}
}
}
配置了mongo实例和morphia之后,我们要创建datastore了。
public class DatastoreFactoryBean extends AbstractFactoryBean<Datastore> {
// morphia实例,最好是单例
private Morphia morphia;
// mongoClient实例,最好是单例
private MongoClient mongoClient;
// 数据库名
private String dbName;
// 用户名,可为空
private String username;
// 密码,可为空
private String password;
// 是否确认索引存在,默认false
private boolean toEnsureIndexes = false;
// 是否确认caps存在,默认false
private boolean toEnsureCaps = false;
@Override
protected Datastore createInstance() throws Exception {
Datastore ds = morphia.createDatastore(mongoClient, dbName);
if (toEnsureIndexes) {
ds.ensureIndexes();
}
if (toEnsureCaps) {
ds.ensureCaps();
}
return ds;
}
public Morphia getMorphia() {
return morphia;
}
public void setMorphia(Morphia morphia) {
this.morphia = morphia;
}
public MongoClient getMongoClient() {
return mongoClient;
}
public void setMongoClient(MongoClient mongoClient) {
this.mongoClient = mongoClient;
}
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 toEnsureCaps;
}
public void setToEnsureCaps(boolean toEnsureCaps) {
this.toEnsureCaps = toEnsureCaps;
}
@Override
public Class<?> getObjectType() {
return Datastore.class;
}
@Override
public void afterPropertiesSet() throws Exception {
super.afterPropertiesSet();
if (mongoClient == null) {
throw new IllegalStateException("mongoClient is not set");
}
if (morphia == null) {
throw new IllegalStateException("morphia is not set");
}
}
}
配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd"
default-lazy-init="true">
<!-- 使用工厂创建mongo实例 -->
<bean id="mongoClient" class="com.test.mongo.MongoFactoryBean">
<!-- 设定服务器列表,默认为localhost:27017 -->
<property name="serverStrings">
<array>
<value>127.0.0.1:27017</value>
</array>
</property>
</bean>
<!-- 使用工厂创建morphia实例,同时完成类映射操作 -->
<bean id="morphia" class="com.test.mongo.MorphiaFactoryBean">
<!-- 指定要扫描的POJO包路径 -->
<property name="mapPackages">
<array>
<value>com.test.model</value>
</array>
</property>
<!-- 指定要映射的类 -->
<!--<property name="mapClasses">
<array>
</array>
</property>-->
<!-- 扫描包时是否忽略不可用的类,默认为false -->
<property name="ignoreInvalidClasses" value="false"/>
</bean>
<!-- 使用工厂创建datastore,同时完成index和caps的确认操作 -->
<bean id="datastore" class="com.test.mongo.DatastoreFactoryBean">
<property name="morphia" ref="morphia" />
<property name="mongoClient" ref="mongoClient" />
<!-- collection的名称 -->
<property name="dbName" value="${mongo.server.dbName}" />
<!-- 用户名和密码可以为空 -->
<property name="username" value="${mongo.server.user}" />
<property name="password" value="${mongo.server.pwd}" />
<!-- 是否进行index和caps的确认操作,默认为flase -->
<property name="toEnsureIndexes" value="true" />
<property name="toEnsureCaps" value="true" />
</bean>
</beans>
配置Entity
@Entity(noClassnameStored = true)
@Indexes(@Index("bookName,authorName"))
public class Book {
@Id
private ObjectId id;
private String bookName;
private String status;
private String authorName;
private String label;
private String description;
private String url;
public ObjectId getId() {
return id;
}
public void setId(ObjectId id) {
this.id = id;
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getAuthorName() {
return authorName;
}
public void setAuthorName(String authorName) {
this.authorName = authorName;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
配置dao
@Component
public class WebpageDao extends BasicDAO<Book, ObjectId> {
//实例化该类的时候注入Datastore
//所有的增删改查都是基于datastore的方法
@Autowired
public WebpageDao(Datastore ds) {
super(ds);
}
public long findByInfo(String bookName, String authorName) {
Query<Book> query = getDatastore().createQuery(Book.class)
.field("bookName").equal(bookName)
.field("authorName").equal(authorName);
return count(query);
}
}
以上就是简单的morphia的使用案例,当然morphia还有很多特质的属性,如利用MappingOption类去配置多种映射选项。@Entity中还有很多的annotation等等,上述额外的特性需要自己去在项目中多多运用。