1. 程式人生 > >morphia與spring的整合

morphia與spring的整合

簡單的來說Morphia與MongoDB的關係就如Hibernate與關係資料庫的關係, 是一個實現Java物件到MongoDB雙向對映的類庫。

首先我們需要一個生成和配置mongodb的工廠類:

[java] view plain copy print?在CODE上檢視程式碼片派生到我的程式碼片
  1. publicclass MongoFactoryBean extends AbstractFactoryBean<Mongo> {  
  2.     // 表示伺服器列表(主從複製或者分片)的字串陣列
  3.     private String[] serverStrings;  
  4.     // mongoDB配置物件
  5.     private
     MongoOptions mongoOptions;  
  6.     // 是否主從分離(讀取從庫),預設讀寫都在主庫
  7.     privateboolean readSecondary = false;  
  8.     // 設定寫策略(出錯時是否拋異常),預設採用SAFE模式(需要拋異常)
  9.     private WriteConcern writeConcern = WriteConcern.SAFE;  
  10.     @Override
  11.     public Class<?> getObjectType() {  
  12.         return Mongo.class;  
  13.     }  
  14.     @Override
  15.     protected Mongo createInstance() throws Exception {  
  16.         Mongo mongo = initMongo();  
  17.         // 設定主從分離
  18.         if (readSecondary) {  
  19.             mongo.setReadPreference(ReadPreference.secondaryPreferred());  
  20.         }  
  21.         // 設定寫策略
  22.         mongo.setWriteConcern(writeConcern);  
  23.         return mongo;  
  24.     }  
  25.     /** 
  26.      * 初始化mongo例項 
  27.      * @return 
  28.      * @throws Exception 
  29.      */
  30.     private Mongo initMongo() throws Exception {  
  31.         // 根據條件建立Mongo例項
  32.         Mongo mongo = null;  
  33.         List<ServerAddress> serverList = getServerList();  
  34.         if (serverList.size() == 0) {  
  35.             mongo = new Mongo();  
  36.         }elseif(serverList.size() == 1){  
  37.             if (mongoOptions != null) {  
  38.                 mongo = new Mongo(serverList.get(0), mongoOptions);  
  39.             }else{  
  40.                 mongo = new Mongo(serverList.get(0));  
  41.             }  
  42.         }else{  
  43.             if (mongoOptions != null) {  
  44.                 mongo = new Mongo(serverList, mongoOptions);  
  45.             }else{  
  46.                 mongo = new Mongo(serverList);  
  47.             }  
  48.         }  
  49.         return mongo;  
  50.     }  
  51.     /** 
  52.      * 根據伺服器字串列表,解析出伺服器物件列表 
  53.      * <p> 
  54.      *  
  55.      * @Title: getServerList 
  56.      *         </p> 
  57.      *  
  58.      * @return 
  59.      * @throws Exception 
  60.      */
  61.     private List<ServerAddress> getServerList() throws Exception {  
  62.         List<ServerAddress> serverList = new ArrayList<ServerAddress>();  
  63.         try {  
  64.             for (String serverString : serverStrings) {  
  65.                 String[] temp = serverString.split(":");  
  66.                 String host = temp[0];  
  67.                 if (temp.length > 2) {  
  68.                     thrownew IllegalArgumentException(  
  69.                             "Invalid server address string: " + serverString);  
  70.                 }  
  71.                 if (temp.length == 2) {  
  72.                     serverList.add(new ServerAddress(host, Integer  
  73.                             .parseInt(temp[1])));  
  74.                 } else {  
  75.                     serverList.add(new ServerAddress(host));  
  76.                 }  
  77.             }  
  78.             return serverList;  
  79.         } catch (Exception e) {  
  80.             thrownew Exception(  
  81.                     "Error while converting serverString to ServerAddressList",  
  82.                     e);  
  83.         }  
  84.     }  
  85.     /* ------------------- setters --------------------- */
  86. }  
public class MongoFactoryBean extends AbstractFactoryBean<Mongo> {

    // 表示伺服器列表(主從複製或者分片)的字串陣列
    private String[] serverStrings;
    // mongoDB配置物件
    private MongoOptions mongoOptions;
    // 是否主從分離(讀取從庫),預設讀寫都在主庫
    private boolean readSecondary = false;
    // 設定寫策略(出錯時是否拋異常),預設採用SAFE模式(需要拋異常)
    private WriteConcern writeConcern = WriteConcern.SAFE;

    @Override
    public Class<?> getObjectType() {
        return Mongo.class;
    }

    @Override
    protected Mongo createInstance() throws Exception {
        Mongo mongo = initMongo();
        
        // 設定主從分離
        if (readSecondary) {
            mongo.setReadPreference(ReadPreference.secondaryPreferred());
        }

        // 設定寫策略
        mongo.setWriteConcern(writeConcern);
        return mongo;
    }
    
    /**
     * 初始化mongo例項
     * @return
     * @throws Exception
     */
    private Mongo initMongo() throws Exception {
        // 根據條件建立Mongo例項
        Mongo mongo = null;
        List<ServerAddress> serverList = getServerList();

        if (serverList.size() == 0) {
            mongo = new Mongo();
        }else if(serverList.size() == 1){
            if (mongoOptions != null) {
                mongo = new Mongo(serverList.get(0), mongoOptions);
            }else{
                mongo = new Mongo(serverList.get(0));
            }
        }else{
            if (mongoOptions != null) {
                mongo = new Mongo(serverList, mongoOptions);
            }else{
                mongo = new Mongo(serverList);
            }
        }
        return mongo;
    }
    
    
    /**
     * 根據伺服器字串列表,解析出伺服器物件列表
     * <p>
     * 
     * @Title: getServerList
     *         </p>
     * 
     * @return
     * @throws Exception
     */
    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);
                }
                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);
        }
    }

    /* ------------------- setters --------------------- */
}

其次我們需要一個產生和配置morphia物件的工廠類:

[java] view plain copy print?在CODE上檢視程式碼片派生到我的程式碼片
  1. publicclass MorphiaFactoryBean extends AbstractFactoryBean<Morphia> {  
  2.      /** 
  3.       * 要掃描並對映的包 
  4.       */
  5.      private String[] mapPackages;    
  6.      /** 
  7.       * 要對映的類 
  8.       */
  9.      private String[] mapClasses;    
  10.      /** 
  11.       * 掃描包時,是否忽略不對映的類 
  12.       * 這裡按照Morphia的原始定義,預設設為false 
  13.       */
  14.      privateboolean ignoreInvalidClasses;  
  15.      @Override
  16.      protected Morphia createInstance() throws Exception {  
  17.          Morphia m = new Morphia();  
  18.          if (mapPackages != null) {  
  19.              for (String packageName : mapPackages) {  
  20.                  m.mapPackage(packageName, ignoreInvalidClasses);  
  21.              }  
  22.          }  
  23.          if (mapClasses != null) {    
  24.              for (String entityClass : mapClasses) {  
  25.                  m.map(Class.forName(entityClass));  
  26.              }  
  27.          }  
  28.          return m;  
  29.      }  
  30.      @Override
  31.      public Class<?> getObjectType() {  
  32.          return Morphia.class;  
  33.      }  
  34.      /*----------------------setters-----------------------*/
  35.  }  
public class MorphiaFactoryBean extends AbstractFactoryBean<Morphia> {
     /**
      * 要掃描並對映的包
      */
     private String[] mapPackages;  
     
     /**
      * 要對映的類
      */
     private String[] mapClasses;  
     
     /**
      * 掃描包時,是否忽略不對映的類
      * 這裡按照Morphia的原始定義,預設設為false
      */
     private boolean ignoreInvalidClasses;
     
     @Override
     protected Morphia createInstance() throws Exception {
         Morphia m = new Morphia();
         if (mapPackages != null) {
             for (String packageName : mapPackages) {
                 m.mapPackage(packageName, ignoreInvalidClasses);
             }
         }
         if (mapClasses != null) {  
             for (String entityClass : mapClasses) {
                 m.map(Class.forName(entityClass));
             }
         }
         return m;
     }
 
     @Override
     public Class<?> getObjectType() {
         return Morphia.class;
     }
     
     /*----------------------setters-----------------------*/
 }


最後我們還需要一個產生和配置Datastore的工廠類:

[java] view plain copy print?在CODE上檢視程式碼片派生到我的程式碼片
  1. publicclass DatastoreFactoryBean extends AbstractFactoryBean<Datastore> {  
  2.      private Morphia morphia;    //morphia例項,最好是單例
  3.      private Mongo mongo;    //mongo例項,最好是單例
  4.      private String dbName;    //資料庫名
  5.      private String username;    //使用者名稱,可為空
  6.      private String password;    //密碼,可為空
  7.      privateboolean toEnsureIndexes=false;    //是否確認索引存在,預設false
  8.      privateboolean toEnsureCaps=false;    //是否確認caps存在,預設false
  9.      @Override
  10.      protected Datastore createInstance() throws Exception {  
  11.          //這裡的username和password可以為null,morphia物件會去處理
  12.          Datastore ds = morphia.createDatastore(mongo, dbName, username,  
  13.                  password==null?null:password.toCharArray());  
  14.          if(toEnsureIndexes){  
  15.              ds.ensureIndexes();  
  16.          }  
  17.          if(toEnsureCaps){  
  18.              ds.ensureCaps();  
  19.          }  
  20.          return ds;  
  21.      }  
  22.      @Override
  23.      public Class<?> getObjectType() {  
  24.          return Datastore.class;  
  25.      }  
  26.      @Override
  27.      publicvoid afterPropertiesSet() throws Exception {  
  28.          super.afterPropertiesSet();  
  29.          if (mongo == null) {  
  30.              thrownew IllegalStateException("mongo is not set");  
  31.          }  
  32.          if (morphia == null) {  
  33.              thrownew IllegalStateException("morphia is not set");  
  34.          }  
  35.      }  
  36.      /*----------------------setters-----------------------*/
  37.  }  
public class DatastoreFactoryBean extends AbstractFactoryBean<Datastore> {
     
     private Morphia morphia;    //morphia例項,最好是單例
     private Mongo mongo;    //mongo例項,最好是單例
     private String dbName;    //資料庫名
     private String username;    //使用者名稱,可為空
     private String password;    //密碼,可為空
     private boolean toEnsureIndexes=false;    //是否確認索引存在,預設false
     private boolean toEnsureCaps=false;    //是否確認caps存在,預設false
     
 
     @Override
     protected Datastore createInstance() throws Exception {
         //這裡的username和password可以為null,morphia物件會去處理
         Datastore ds = morphia.createDatastore(mongo, dbName, username,
                 password==null?null:password.toCharArray());
         if(toEnsureIndexes){
             ds.ensureIndexes();
         }
         if(toEnsureCaps){
             ds.ensureCaps();
         }
         return ds;
     }
 
     @Override
     public Class<?> getObjectType() {
         return Datastore.class;
     }
 
     @Override
     public void afterPropertiesSet() throws Exception {
         super.afterPropertiesSet();
         if (mongo == null) {
             throw new IllegalStateException("mongo is not set");
         }
         if (morphia == null) {
             throw new IllegalStateException("morphia is not set");
         }
     }
     
     /*----------------------setters-----------------------*/
 }


我們來仿照morphia文件,寫兩個測試的POJO:

[java] view plain copy print?在CODE上檢視程式碼片派生到我的程式碼片
  1. @Entity
  2.  publicclass Hotel {  
  3.      @Idprivate ObjectId id;  
  4.      private String name;  
  5.      privateint stars;  
  6.      @Embedded
  7.      private Address address;      
  8.      /*-----------gettters & setters----------*/
  9.  }  
@Entity
 public class Hotel {
     @Id private ObjectId id;
     
     private String name;
     private int stars;
     
     @Embedded
     private Address address;    
     
     /*-----------gettters & setters----------*/
 }
[java] view plain copy print?在CODE上檢視程式碼片派生到我的程式碼片
  1. @Embedded
  2. publicclass Address {  
  3.     private String street;  
  4.     private String city;  
  5.     private String postCode;  
  6.     private String country;  
  7.     /*-----------gettters & setters----------*/
  8. }  
@Embedded
public class Address {
    private String street;
    private String city;
    private String postCode;
    private String country;
    /*-----------gettters & setters----------*/
}

還需要一個為測試POJO專門服務的DAO,這裡繼承morphia裡的BasicDAO:

[java] view plain copy print?在CODE上檢視程式碼片派生到我的程式碼片
  1. publicclass HotelDAO extends BasicDAO<Hotel, ObjectId> {  
  2.     protected HotelDAO(Datastore ds) {  
  3.         super(ds);  
  4.     }  
  5.     /* ----------------以下是自定義的資料查詢方法(finder)----------------- */
  6. }  
public class HotelDAO extends BasicDAO<Hotel, ObjectId> {

    protected HotelDAO(Datastore ds) {
        super(ds);
    }
    
    /* ----------------以下是自定義的資料查詢方法(finder)----------------- */
}



最後是spring的XML檔案:

[html] view plain copy print?在CODE上檢視程式碼片派生到我的程式碼片
  1. <?xmlversion="1.0"encoding="UTF-8"?>
  2. <beansxmlns="http://www.springframework.org/schema/beans"
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"
  4.     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd   
  5.     http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
  6.     <!-- 配置檔案 -->
  7.     <context:property-placeholderlocation="classpath:config.properties"/>
  8.     <!-- mongoDB的配置物件 -->
  9.     <beanid="mongoOptions"class="com.mongodb.MongoOptions">
  10.         <!-- 伺服器是否自動重連,預設為false -->
  11.         <propertyname="autoConnectRetry"value="false"/>
  12.         <!-- 對同一個伺服器嘗試重連的時間(毫秒),設為0時預設使用15秒 -->
  13.         <propertyname="maxAutoConnectRetryTime"value="0"/>
  14.         <!-- 與每個主機的連線數,預設為10 -->
  15.         <propertyname="connectionsPerHost"value="10"/>
  16.         <!-- 連線超時時間(毫秒),預設為10000 -->
  17.         <propertyname="connectTimeout"value="10000"/>
  18.         <!-- 是否建立一個finalize方法,以便在客戶端沒有關閉DBCursor的例項時,清理掉它。預設為true -->
  19.         <propertyname="cursorFinalizerEnabled"value="true"/>
  20.         <!-- 執行緒等待連線可用的最大時間(毫秒),預設為120000 -->
  21.         <propertyname="maxWaitTime"value="120000"/>
  22.         <!-- 可等待執行緒倍數,預設為5.例如connectionsPerHost最大允許10個連線,則10*5=50個執行緒可以等待,更多的執行緒將直接拋異常 -->
  23.         <propertyname="threadsAllowedToBlockForConnectionMultiplier"value="5"/>
  24.         <!-- socket讀寫時超時時間(毫秒),預設為0,不超時 -->
  25.         <propertyname="socketTimeout"value="0"/>
  26.         <!-- 是socket連線在防火牆上保持活動的特性,預設為false -->
  27.         <propertyname="socketKeepAlive"value="false"/>
  28.         <!-- 對應全域性的WriteConcern.SAFE,預設為false -->
  29.         <propertyname="safe"value="true"/>
  30.         <!-- 對應全域性的WriteConcern中的w,預設為0 -->
  31.         <propertyname="w"value="0"/>
  32.         <!-- 對應全域性的WriteConcern中的wtimeout,預設為0 -->
  33.         <propertyname="wtimeout"value="0"/>
  34.         <!-- 對應全域性的WriteConcern.FSYNC_SAFE,如果為真,每次寫入要等待寫入磁碟,預設為false -->
  35.         <propertyname="fsync"value="false"/>
  36.         <!-- 對應全域性的WriteConcern.JOURNAL_SAFE,如果為真,每次寫入要等待日誌檔案寫入磁碟,預設為false -->
  37.         <propertyname="j"value="false"/>
  38.     </bean>
  39.     <!-- 使用工廠建立mongo例項 -->
  40.     <beanid="mongo"class="me.watchzerg.test.morphia.spring.MongoFactoryBean">
  41.         <!-- mongoDB的配置物件 -->
  42.         <propertyname="mongoOptions"ref="mongoOptions"/>
  43.         <!-- 是否主從分離(讀取從庫),預設為false,讀寫都在主庫 -->
  44.         <propertyname="readSecondary"value="false"/>
  45.         <!-- 設定寫策略,預設為WriteConcern.SAFE,優先順序高於mongoOptions中的safe -->
  46.         <propertyname="writeConcern"value="SAFE"/>
  47.         <!-- 設定伺服器列表,預設為localhost:27017 -->
  48.         <propertyname="serverStrings">
  49.             <array>
  50.                 <value>${mongoDB.server}</value>
  51.             </array>
  52.         </property>
  53.     </bean>
  54.     <!-- 使用工廠建立morphia例項,同時完成類對映操作 -->
  55.     <beanid="morphia"class="me.watchzerg.test.morphia.spring.MorphiaFactoryBean">
  56.         <!-- 指定要掃描的POJO包路徑 -->
  57.         <propertyname="mapPackages">
  58.             <array>
  59.                 <value>me.watchzerg.test.morphia.pojo</value>
  60.             </array>
  61.         </property>
  62.         <!-- 指定要對映的類 -->
  63.         <!-- <propertyname="mapClasses">
  64.             <array>
  65.                 <value>me.watchzerg.test.morphia.pojo.Hotel</value>
  66.                 <value>me.watchzerg.test.morphia.pojo.Address</value>
  67.             </array>
  68.         </property> -->
  69.         <!-- 掃描包時是否忽略不可用的類,預設為false -->
  70.         <!-- <property name="ignoreInvalidClasses" value="false"/> -->
  71.     </bean>
  72.     <!-- 使用工廠建立datastore,同時完成index和caps的確認操作 -->
  73.     <beanid="datastore"class="me.watchzerg.test.morphia.spring.DatastoreFactoryBean">
  74.         <propertyname="morphia"ref="morphia"/>
  75.         <propertyname="mongo"ref="mongo"/>
  76.         <!-- collection的名稱 -->
  77.         <propertyname="dbName"value="${mongoDB.dbName}"/>
  78.         <!-- 使用者名稱和密碼可以為空 -->
  79.         <!-- <propertyname="username"value="my_username"/>
  80.         <propertyname="password"value="my_password"/> -->
  81.         <!-- 是否進行index和caps的確認操作,預設為flase -->
  82.         <propertyname="toEnsureIndexes"value="true"/>
  83.         <propertyname="toEnsureCaps"value="true"/>
  84.     </bean>
  85.     <!-- ===============以下是具體DAO的實現===================== -->
  86.     <beanid="hotelDAO"class="me.watchzerg.test.morphia.dao.impl.HotelDAO">
  87.         <constructor-argref="datastore"/>
  88.     </bean>
  89. </beans>
<?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd 
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">  
    
    <!-- 配置檔案 -->
    <context:property-placeholder location="classpath:config.properties" />
    
    <!-- mongoDB的配置物件 -->
    <bean id="mongoOptions" class="com.mongodb.MongoOptions">
        <!-- 伺服器是否自動重連,預設為false -->
        <property name="autoConnectRetry" value="false" />
        <!-- 對同一個伺服器嘗試重連的時間(毫秒),設為0時預設使用15秒 -->
        <property name="maxAutoConnectRetryTime" value="0" />
        <!-- 與每個主機的連線數,預設為10 -->
        <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="me.watchzerg.test.morphia.spring.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>${mongoDB.server}</value>
            </array>
        </property>
    </bean>
    
    
    <!-- 使用工廠建立morphia例項,同時完成類對映操作 -->
    <bean id="morphia" class="me.watchzerg.test.morphia.spring.MorphiaFactoryBean" >
        <!-- 指定要掃描的POJO包路徑 -->
        <property name="mapPackages">
            <array>
                <value>me.watchzerg.test.morphia.pojo</value>
            </array>
        </property>
        
        <!-- 指定要對映的類 -->
        <!-- <property name="mapClasses">
            <array>
                <value>me.watchzerg.test.morphia.pojo.Hotel</value>
                <value>me.watchzerg.test.morphia.pojo.Address</value>
            </array>
        </property> -->
        
        <!-- 掃描包時是否忽略不可用的類,預設為false -->
        <!-- <property name="ignoreInvalidClasses" value="false"/> -->
    </bean>
    
    <!-- 使用工廠建立datastore,同時完成index和caps的確認操作 -->
    <bean id="datastore" class="me.watchzerg.test.morphia.spring.DatastoreFactoryBean" >
        <property name="morphia" ref="morphia"/>
        <property name="mongo" ref="mongo"/>
        
        <!-- collection的名稱 -->
        <property name="dbName" value="${mongoDB.dbName}"/>
        
        <!-- 使用者名稱和密碼可以為空 -->
        <!-- <property name="username" value="my_username"/>
        <property name="password" value="my_password"/> -->
        
        <!-- 是否進行index和caps的確認操作,預設為flase -->
        <property name="toEnsureIndexes" value="true"/>
        <property name="toEnsureCaps" value="true"/>
    </bean>
    
    <!-- ===============以下是具體DAO的實現===================== -->
    
    <bean id="hotelDAO" class="me.watchzerg.test.morphia.dao.impl.Hot