将 MongoDB 条目转换为 Java Class 模型对象

Convert MongoDB entry to Java Class Model Object

我正在将一个名为 Device 的自定义 java 对象存储到 mongo 集合中。这很好用。但是当我收到数据库条目时,所有内部 class 对象都分配有 null 而不是数据库值。

这是一个设备:

public class Device {

    public String id;

    public String serialNumber;

    public String name;

    public int status;

    public String errorReport;

    public List<Sensor> sensors=new ArrayList<>();

    public List<Action> actions=new ArrayList<>();

    public List<String> filterTags= new ArrayList<>();

    public List protocols;
}

这是数据库中的示例条目,如您所见,值保存得很好:

    {
        "_id": "7_openHabsamsungtv:tv:cbaf7d7d_4e10_41e6_9c1d_864988057bda",
        "actions": [
            {
                "_id": "samsungtv:tv:cbaf7d7d_4e10_41e6_9c1d_864988057bda:volume",
                "deviceId": "7_openHabsamsungtv:tv:cbaf7d7d_4e10_41e6_9c1d_864988057bda",
                "errorReport": "Value wurde nicht initialisiert",
                "name": "Lautst�rke",
                "state": 0,
                "value": 0,
                "valueOption": {
                    "maximum": 0,
                    "minimum": 0,
                    "percentage": true
                },
                "valueable": true
            }
    ],
    "filterTags": [],
        "name": "[TV] Chine ",
        "sensors": [
            {
                "_id": "samsungtv:tv:cbaf7d7d_4e10_41e6_9c1d_864988057bda:sourceId",
                "name": "Source ID"
            },
            {
                "_id": "samsungtv:tv:cbaf7d7d_4e10_41e6_9c1d_864988057bda:programTitle",
                "name": "Titel"
            },
            {
                "_id": "samsungtv:tv:cbaf7d7d_4e10_41e6_9c1d_864988057bda:channelName",
                "name": "Kanal"
            }
        ],
        "status": 0
    }

这就是我再次从数据库接收它时的样子:

{
        "id": "7_openHabsamsungtv:tv:cbaf7d7d_4e10_41e6_9c1d_864988057bda",
        "serialNumber": null,
        "name": "[TV] Chine ",
        "status": 0,
        "errorReport": null,
        "sensors": [
            {
                "id": null,
                "name": null,
                "errorReport": null
            },
            {
                "id": null,
                "name": null,
                "errorReport": null
            },
            {
                "id": null,
                "name": null,
                "errorReport": null
            }
        ],
        "actions": [
            {
                "id": null,
                "name": null,
                "deviceId": null,
                "state": 0,
                "states": null,
                "valueOption": null,
                "value": 0,
                "errorReport": "Value wurde nicht initialisiert",
                "valueable": false
            }
],
        "filterTags": [],
        "protocols": null
    }

因此,当我从我的数据库集合中提取条目时,它会将 SensorAction 的值设置为空。这是我的 Java 接收设备的代码:

MongoClientURI connectionString = new MongoClientURI(dummy);
MongoClient mongoClient = new MongoClient(connectionString);
CodecRegistry pojoCodecRegistry = fromRegistries(MongoClient.getDefaultCodecRegistry(),
fromProviders(PojoCodecProvider.builder().automatic(true).build()));
MongoCollection<Device> devices = database.withCodecRegistry(pojoCodecRegistry).getCollection("devices", Device.class);

Device device = devices.find().first();

我正在使用标准 MongoDB Java 驱动程序。 谁能告诉我我在这里缺少什么?提前致谢。

TL;DR:每个默认配置都需要 setter 和 getter。

我写这个 Unit-Test 是为了重现错误,但它不会重现,除非我使用 Action 和 Sensor classes。我正在使用 Mongodb 3.4 和 Java 驱动程序 3.6.

import com.mongodb.MongoClient;
import com.mongodb.MongoClientURI;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.codecs.configuration.CodecRegistry;
import org.bson.codecs.pojo.PojoCodecProvider;
import org.junit.Test;

import static org.bson.codecs.configuration.CodecRegistries.fromProviders;
import static org.bson.codecs.configuration.CodecRegistries.fromRegistries;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertNotNull;

public class MongoDeser {

    @Test
    public void testDeser() {
        MongoClientURI connectionString = new MongoClientURI("mongodb://localhost:27017");
        MongoClient mongoClient = new MongoClient(connectionString);
        MongoDatabase database = mongoClient.getDatabase("sotest");
        PojoCodecProvider codecProvider = PojoCodecProvider.builder()
                .automatic(true)
                .build();

        CodecRegistry pojoCodecRegistry = fromRegistries(MongoClient.getDefaultCodecRegistry(), fromProviders(codecProvider));

        MongoCollection<Device> devices = database.withCodecRegistry(pojoCodecRegistry).getCollection("device", Device.class);

        Device device = devices.find().first();

        assertNotNull(device.getActions());
        assertThat(device.getActions().size(), is(1));
        assertThat(device.getActions().get(0).getDeviceId(), is("7_openHabsamsungtv:tv:cbaf7d7d_4e10_41e6_9c1d_864988057bda"));
        assertThat(device.getStatus(), is(0));
        assertThat(device.getName(), is("[TV] Chine "));
    }

}

您的 POJO 中是否缺少 getter and/or setter?

Mongodb Java 驱动程序 uses reflection 用于从 BSON 映射 POJO。每个默认配置都需要这些 Getters 和 Setters。如果您没有它们,它的行为可能会不稳定。在我的测试中,有时它找不到编解码器并抛出异常,有时字段就像您的情况一样被清空。我的建议是改用注解,并为 Java 驱动程序指定一个约定。

传感器class

import java.io.Serializable;

public class Sensor implements Serializable
{

    private String id;
    private String name;
    private final static long serialVersionUID = 8244091126694748358L;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

操作class

import java.io.Serializable;

public class Action implements Serializable
{

    private String id;
    private String deviceId;
    private String errorReport;
    private String name;
    private long state;
    private long value;
    private ValueOption valueOption;
    private boolean valueable;
    private final static long serialVersionUID = 3493217442158516855L;

    public String getId() {
        return id;
    }

    public String getDeviceId() {
        return deviceId;
    }

    public String getErrorReport() {
        return errorReport;
    }

    public String getName() {
        return name;
    }

    public long getState() {
        return state;
    }

    public long getValue() {
        return value;
    }

    public ValueOption getValueOption() {
        return valueOption;
    }

    public boolean isValueable() {
        return valueable;
    }

    public static long getSerialVersionUID() {
        return serialVersionUID;
    }

    public void setId(String id) {
        this.id = id;
    }

    public void setDeviceId(String deviceId) {
        this.deviceId = deviceId;
    }

    public void setErrorReport(String errorReport) {
        this.errorReport = errorReport;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setState(long state) {
        this.state = state;
    }

    public void setValue(long value) {
        this.value = value;
    }

    public void setValueOption(ValueOption valueOption) {
        this.valueOption = valueOption;
    }

    public void setValueable(boolean valueable) {
        this.valueable = valueable;
    }
}
CodecRegistry codecRegistry = CodecRegistries.fromRegistries(
CodecRegistries.fromProviders(new pojoCodecRegistryCodecProvider()),
CodecRegistries.fromProviders(new ActionCodecProvider()),
CodecRegistries.fromProviders(new SensorCodecProvider()));