问题
I am storing a custom java object called Device
into a mongo collection. This works fine. But when I am receiving the database entry all inner class objects are assigned with null
and not with the database value.
This is a device:
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;
}
This is an example entry from the database, as you can see the values are saved well:
{
"_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
}
And this is what it looks like when I am receiving it from the database again:
{
"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
}
So when I am pulling the entries from my db collection it sets the values of the Sensor
and Action
to null. This is my Java Code for receiving a device:
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();
I am using the standard MongoDB Java Driver. Could anyone tell me what I am missing here? Thanks in advance.
回答1:
TL;DR: You need setters and getters per default config.
I wrote this Unit-Test to reproduce the error, but it does not reproduce except when I play around with the Action and Sensor classes. I am using Mongodb 3.4 and Java driver 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 "));
}
}
Do you have missing getters and/or setters in your POJOs?
Mongodb Java driver uses reflection for mapping POJOs from BSON. It needs these Getters and Setters per default configuration. If you don't have them, it may behave erratically. In my testing, sometimes it couldn't find a codec and threw an exception, sometimes the fields were just nulled as in your case. My recommendation would be to use annotations instead and give the Java driver a convention for it.
Sensor 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;
}
}
Action 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;
}
}
回答2:
CodecRegistry codecRegistry = CodecRegistries.fromRegistries(
CodecRegistries.fromProviders(new pojoCodecRegistryCodecProvider()),
CodecRegistries.fromProviders(new ActionCodecProvider()),
CodecRegistries.fromProviders(new SensorCodecProvider()));
来源:https://stackoverflow.com/questions/49450426/convert-mongodb-entry-to-java-class-model-object