欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Spring boot配置MongoDB以及Morphia踩坑记录

程序员文章站 2022-05-26 14:27:54
pom 因为项目中采用 (`MongoDB ORM pom`文件中引入相应依赖: 因为 依赖于 ,因此无需在 文件中继续导入 . 配置 (1) 配置文件 中配置如下所示: 上述配置中, 包围的地方请按照各自项目实际情况填写. (2) 代码配置 代码中无需自行配置 (`Spring boot Mong ......

pom

因为项目中采用morphia(mongodborm框架),因此需要在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属性
     */
    @autowired
    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接口比较明晰,容易入门.