1. 程式人生 > >【Mongodb】morphia與spring結合使用詳解

【Mongodb】morphia與spring結合使用詳解

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