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
@Componentpublic 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等等,上述額外的特性需要自己去在項目中多多運用。