Spring boot配置MongoDB以及Morphia踩坑記錄


pom

因為項目中采用Morphia(MongoDBODM框架,對象-文檔映射(object-document mapper)),因此需要在pom文件中引入相應依賴:

        <dependency>
            <groupId>dev.morphia.morphia</groupId>
            <artifactId>core</artifactId>
            <version>1.5.3</version>
        </dependency>

因為Morphia依賴於mongo-java-driver,因此無需在pom文件中繼續導入mongo-java-driver.

配置

(1) 配置文件

application.yaml中配置如下所示:

  data:
    mongodb:
      database: {數據庫名稱}
      uri: mongodb://{用戶名}:{密碼}@{服務器地址}:27017/{數據庫名稱}

上述配置中,{}包圍的地方請按照各自項目實際情況填寫.

(2) 代碼配置

@Data
@Configuration
public class MorphiaConfig {

    private MongoClient mongoClient;

    /**
     * 設置連接最大空閑時間(到達時間,連接關閉)
     * @return mongo client屬性
     */
    @Bean
    public MongoClientOptions mongoClientOptions() {
        return MongoClientOptions.builder()
                .maxConnectionIdleTime(6000 * 5)
                .maxConnectionLifeTime(0)
                .build();
    }

    @Autowired
    public MorphiaConfig(MongoClient mongoClient) {
        this.mongoClient = mongoClient;
    }

    @Bean
    public Datastore datastore(@Autowired MongoClient mongoClient) {
        Morphia res = new Morphia();
        // 確定Mongo實體類的存放包名
        res.mapPackage("com.test.log.entity");
        Datastore datastore = res.createDatastore(mongoClient, "ops");
        //  為實體類創建索引
        datastore.ensureIndexes();
        return datastore;
    }
}

代碼中無需自行配置MongoClient(Spring boot會自動完成MongoClient的初始化),當然也允許自行設置Mongo的連接參數.

實體類

項目中需要存放日志,並且通過MongoDBTTL特性設置過期時間,以便通過MongoDB完成日志刪除任務.

@Builder
@NoArgsConstructor
@AllArgsConstructor
@Data
// 必須添加,以便Morphia識別此類為`MongoDB`的實體類,`logInfo`是表名
@Entity(value = "logInfo", noClassnameStored = true)
@Indexes({
        // expireTime存放日志過期時間,創建TTL index
        @Index(fields = @Field(value = "expireTime"), options = @IndexOptions(expireAfterSeconds = 0)),
        // 創建復合索引
        @Index(fields = {@Field("deviceId"), @Field("module"), @Field(value = "time", type = DESC)}),
        @Index(fields = {@Field("deviceId"), @Field(value = "time", type = DESC)})
})
public class LogInfo {
    @Id
    private ObjectId id;
    private Date time;
    @JsonIgnore
    private Date expireTime;
    private String module;
    private String level;
    private String deviceId;
    private String msg;
}

日志的存放和讀取是在不同的項目完成,在查詢MongoDB時遇到反序列化問題,異常如下所示:

WARN  dev.morphia.mapping.DefaultCreator - Class not found defined in dbObj:

查詢源碼分析,是因為Morphia在存儲數據的時候,會將實體類名稱存入數據庫中.
查詢時Morphia根據類名查找相應的實體類並進行反序列化.
因為不同的項目中,實體類的包名不一致導致出現以上錯誤.
解決方案比較簡單,通過注解告知Morphia存儲數據時不要存儲包名即可,具體如下所示:

`@Entity(value = "logInfo", noClassnameStored = true)`.

CRUD操作

(1) 存儲操作

    LogInfo logInfo = LogInfo.builder()
            .time(dateTime)
            .expireTime(dateExpireTime)
            .level(level)
            .module(module)
            .deviceId(deviceId)
            .msg(msg)
            .build();
            try {
        //插入日志到mongoDB
        datastore.save(logInfo);
    } catch (RuntimeException e) {
        log.error(AppStatus.IDB_WRITE_FAIL.getError(), e);
    }

(2) 查詢操作

    final Query<LogInfo> query = datastore.createQuery(LogInfo.class).filter("deviceId = ",     request.getDeviceId());
    // 列表查詢
    if (!CollectionUtils.isEmpty(request.getModules())) {
        query.filter("module in ", request.getModules().toArray());
    }
    // 根據時間查詢,使用filter就不太恰當了
    if (null != request.getStartTime()) {
        query.field("time").greaterThanOrEq(request.getStartTime());
    }
    if (null != request.getFinishTime()) {
        query.field("time").lessThanOrEq(request.getFinishTime());
    }

    // 查詢記錄總數
    int count = query.count());

    // 設置排序規則,查詢具體數據
    query.order(Sort.descending("time"));
    // 獲取數據游標
    MongoCursor<LogInfo> logInfoMongoCursor = query.find(
            new FindOptions()
                .skip((request.getPageNum() - 1) * request.getPageSize())
                .limit(request.getPageSize())
        );
    // 通過數據游標,逐個獲取數據記錄
    while (logInfoMongoCursor.hasNext()) {
        logInfoPage.add(logInfoMongoCursor.next());
    }

刪除以及更新操作就不再贅述,Morphia接口比較明晰,容易入門.

PS:
如果您覺得我的文章對您有幫助,請關注我的微信公眾號,謝謝!
程序員打怪之路


免責聲明!

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



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