将 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
}
因此,当我从我的数据库集合中提取条目时,它会将 Sensor
和 Action
的值设置为空。这是我的 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()));
我正在将一个名为 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
}
因此,当我从我的数据库集合中提取条目时,它会将 Sensor
和 Action
的值设置为空。这是我的 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()));