【原】Spring與MongoDB集成:配置


MongoDB的API提供了DBObject接口來實現BSONObject的操作方法,BasicDBObject是具體實現。但是並沒有提供DBObjectBeanObject的轉換。在還沒有了解到與spring集成之前,我做了一個簡單的轉換,要通過映射和動態調用實現兩個對象的存取。

代碼要處理Bean中的各種類型,並且要控制持久化時的深度:

  • 基礎類型(int, float, boolean...)
  • 基礎擴展類型(Integer, Float, Boolean)
  • 枚舉
  • ObjectId
  • 普通對象 extends Object
  • 業務對象(擁有ObjectId的對象)
  • 容器List, Map, Set(處理元素時要把上面的類型再處理一遍)

雖然代碼可以運行並能達到預期,但知道spring-data-mongo這樣現成的集成功能包時,還是決定換過來。

spring-data-mongo的實現中有一處和我的實現是相似的,就是在mongodb中元素包含了類型信息來做反序列化,我的實現里用_classname來保存類型信息。

 

本文只討論Spring與MongoDB集成的配置,不包括如何使用Mongo、MongoTemplate實例等內容。

spring-data-mongo提供了MongoTemplate來操作bean對象與MongoDB交互,在使用前的關鍵是如何創建一個MongoTemplate來使用。

 

1、依賴包

spring與mongo集成需要很多包,可以手工下載或在運行時通過異常信息下載對應的包,很繁瑣,建議使用Maven來管理依賴。

要加入的依賴有兩個:spring-data-mongo和slf4j的實現,這里選的是slf4j-log4j12。如果不加載slf4j-log4j12,也可以使用其它slf4j的實現,看具體需要。沒有加載的話,運行時會提示錯誤:

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

把下面的依賴加到pom.xml中的<dependencies />節點中

<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-mongodb</artifactId>
    <version>1.2.1.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.5</version>
</dependency>

在pom.xml指定使用的spring版本:

<spring.framework.version>3.1.2.RELEASE</spring.framework.version>

增加spring里程碑倉庫到pom.xml中

<repositories>
    <repository>
        <id>spring-milestone</id>
        <name>Spring Maven MILESTONE Repository</name>
        <url>http://repo.springsource.org/libs-milestone</url>
    </repository>
</repositories>

 

2、集成(連接到MongoDB)

Spring和MongoDB的集成有四種方式,核心就是如何取得MongoTemplate,以及如何設置mongo連接參數,而最終連接到MongoDB上。

1、基本方式

  直接創建MongoTemplate,指定連接時的name,password,database參數等等。這種方式最直接,不需要配置,只要載入相關的jar包。

  MongoTemplate有兩個參數,第一個是com.mongodb.Mongo實例,第二個是字符串型的數據庫名。

  數據庫名不需要解釋了,對於第一個參數,可以直接new Mongo(),並給構造函數傳入適當的參數: 

@Configuration
public class AppConfig {

    public @Bean
    Mongo mongo() throws UnknownHostException {
        return new Mongo( "localhost" );
    }
}

    或者使用MongoFactoryBean創建Mongo實例

@Configuration
public class AppConfig {

    public @Bean
    MongoFactoryBean mongo() {
        MongoFactoryBean mongo = new MongoFactoryBean();
        mongo.setHost( "localhost" );
        return mongo;
    }
}

  無論怎樣,都是手工配置。

2、使用XML注冊Mongo的實例

  使用(Spring)XML注冊Mongo實例的好處是可以方便的配置Mongo參數,還可以簡單的配置集群信息。

<?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:context="http://www.springframework.org/schema/context"
    xmlns:mongo="http://www.springframework.org/schema/data/mongo"
    xsi:schemaLocation="http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/data/mongo
        http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <!-- Default bean name is 'mongo' -->
    <mongo:mongo host="localhost" port="27017" />
</beans>

   如果要配置連接參數可以下面的代碼:

<beans>
    <mongo:mongo host="localhost" port="27017">
        <mongo:options connections-per-host="8"
            threads-allowed-to-block-for-connection-multiplier="4"
            connect-timeout="1000" 
            max-wait-time="1500}" 
            auto-connect-retry="true"
            socket-keep-alive="true" 
            socket-timeout="1500" slave-ok="true"
            write-number="1" 
            write-timeout="0" 
            write-fsync="true" />
    </mongo:mongo/>
</beans>

   配置集群信息:

<mongo:mongo id="replicaSetMongo" replica-set="127.0.0.1:27017,localhost:27018"/> 

  上面兩種方法是圍繞如何直接創建出Mongo實例,而接下來的方法是使用MongoDBFactory來創建DB實例。

3、使用MongoDBFactory

  MongoTemplate的另一組重要構造方法中,有一個是必須的:MongoDBFactory,這是一個接口,定義返回DB實例的方法:

public interface MongoDbFactory {
    
    DB getDb() throws DataAccessException;
    DB getDb(String dbName) throws DataAccessException;
}

  你可以自己實現這個接口,創建Mongo實例,再返回DB的實例。

  spring提供了一個基本的類:org.springframework.data.mongodb.core.SimpleMongoDbFactory,是MongoDbFactory的簡單實現。

  這個類以Mongo實例為參數,可以設置數據庫名作為第二個可選參數;如果有更多的配置項,就使用UserCredentials參數作為第三個可選參數。

  使用下面這段代碼來創建MongoTemplate。里面的SimpleMongoDBFactory和Mongo實例可以手工創建,也可以通過Ico容器來實現。

public class MongoApp {
    private static final Log log = LogFactory.getLog( MongoApp.class );

    public static void main( String[] args ) throws Exception {
        MongoOperations mongoOps = new MongoTemplate( new SimpleMongoDbFactory( new Mongo(), "database" ) );
        mongoOps.insert( new Person( "Joe", 34 ) );
        log.info( mongoOps.findOne( new Query( where( "name" ).is( "Joe" ) ), Person.class ) );
        mongoOps.dropCollection( "person" );
    }
}

  如果使用Bean來配置SimpleMongoDbFactory,代碼大概是這樣:

@Configuration
public class MongoConfiguration {

    public @Bean
    MongoDbFactory mongoDbFactory() throws Exception {
        return new SimpleMongoDbFactory( new Mongo(), "database" );
    }
}

  如果要配置用戶名和密碼,要使用UserCredentials類,向SimpleMongoDbFactory的構造方法傳遞Mongo連接的配置信息:

@Configuration
public class MongoConfiguration {

    public @Bean
    MongoDbFactory mongoDbFactory() throws Exception {
        UserCredentials userCredentials = new UserCredentials( "joe", "secret" );
        return new SimpleMongoDbFactory( new Mongo(), "database", userCredentials );
    }

    public @Bean
    MongoTemplate mongoTemplate() throws Exception {
        return new MongoTemplate( mongoDbFactory() );
    }
}

4、使用XML配置MongoDbFactory實例

  這種方法把所有的配置項放到獨立的配置文件中,使用比較靈活,基本不需要代碼來維護與Mongo連接有關的功能。

  用如下代碼在<beans />節點下簡單配置:

<mongo:db-factory dbname="database">

  或者,配置連接信息:

<mongo:db-factory id="anotherMongoDbFactory" 
    host="localhost"
    port="27017" 
    dbname="database" 
    username="joe" 
    password="secret" />

  一個項目中的spring配置文件內容會比較多,經常修改XML文件並不是一個好辦法。spring提供了另一個方法,可以獨立加載一個properties文件,在個文件里是MongoDB的配置參數。

  通過<context:property-placeholder />節點配置mongo.properties的位置:

<context:property-placeholder
    location="classpath:/com/myapp/mongodb/config/mongo.properties" />

<mongo:mongo host="${mongo.host}" port="${mongo.port}">
    <mongo:options 
        connections-per-host="${mongo.connectionsPerHost}"
        threads-allowed-to-block-for-connection-multiplier="${mongo.threadsAllowedToBlockForConnectionMultiplier}"
        connect-timeout="${mongo.connectTimeout}" 
        max-wait-time="${mongo.maxWaitTime}"
        auto-connect-retry="${mongo.autoConnectRetry}" 
        socket-keep-alive="${mongo.socketKeepAlive}"
        socket-timeout="${mongo.socketTimeout}" 
        slave-ok="${mongo.slaveOk}"
        write-number="1" 
        write-timeout="0" 
        write-fsync="true" />
</mongo:mongo>

<mongo:db-factory dbname="database" mongo-ref="mongo" />

<bean id="anotherMongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
    <constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
</bean>

  <context:property-placeholder />節點的location屬性配置成自己項目中的mongo.properties位置。我的配置文件如下:

mongo.host=127.0.0.1
mongo.port=27017
mongo.connectionsPerHost=8
mongo.threadsAllowedToBlockForConnectionMultiplier=4
mongo.connectTimeout=1500
mongo.maxWaitTime=1500
mongo.autoConnectRetry=true
mongo.socketKeepAlive=true
mongo.socketTimeout=1500
mongo.slaveOk=true

  然后,在代碼中獲取到MongoTemplate的實例:

MongoOperations mongoOps = (MongoTemplate) context.getBean( "anotherMongoTemplate" );

  回頭看看上面XML的配置:

  1. 配置mongo.properties的位置
  2. 配置如何創建Mongo實例,使用了(1)的配置
  3. 配置如何創建MongoDbFactory,使用了(2)的配置
  4. 配置MongoTemplate,使用了(3)的配置

  所以,配置spring與mongodb集成的重點是如何創建MongoTemplate實例。


參考:

spring-data-mongo: http://www.springsource.org/spring-data/mongodb


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM