英文:
MongoDB and java - CodecRegistry only returning an ID field rather than all fields in POJO?
问题
我有以下代码来创建我的Java Spring项目中的Mongo客户端:
CodecRegistry pojoCodecRegistry = fromRegistries(MongoClientSettings.getDefaultCodecRegistry(),
fromProviders(PojoCodecProvider.builder().register(Person.class).automatic(true).build()));
MongoClientSettings settings = MongoClientSettings.builder()
.codecRegistry(pojoCodecRegistry)
.applyConnectionString(new ConnectionString("myConnectionString"))
.build();
MongoClient mongoClient = MongoClients.create(settings);
MongoDatabase database = mongoClient.getDatabase("person").withCodecRegistry(pojoCodecRegistry);
MongoCollection<Person> collection = database.getCollection("personCollection", Person.class).withCodecRegistry(pojoCodecRegistry);
我的Kotlin Pojo是:
@JsonInclude(JsonInclude.Include.NON_NULL)
class Person {
@JsonProperty("_id")
var personID: String? = null
@JsonProperty("name")
var type: String? = null
@JsonProperty("age")
var age: Int? = null
}
我能够获得响应,但响应不如预期,即它是这样的:
{
"persons": [
{
"ID": "personId1"
},
{
"ID": "personId2"
},
{
"ID": "personId3"
}
]
}
每个人对象只显示了一些ID字段,而不是我期望的POJO中的字段。
我在这里缺少什么?我需要为我的Pojo定义自定义编解码器吗?我不确定,因为我是第一次使用这个Mongo库。
英文:
I have the following code to create my mongo client in my Java Spring project:
CodecRegistry pojoCodecRegistry = fromRegistries(MongoClientSettings.getDefaultCodecRegistry(),
fromProviders(PojoCodecProvider.builder().register(Person.class).automatic(true).build()));
MongoClientSettings settings = MongoClientSettings.builder()
.codecRegistry(pojoCodecRegistry)
.applyConnectionString(new ConnectionString("myConnectionStrng"))
.build();
MongoClient mongoClient = MongoClients.create(settings);
MongoDatabase database = mongoClient.getDatabase("person").withCodecRegistry(pojoCodecRegistry);
MongoCollection<Person> collection = database.getCollection("personCollection", Person.class).withCodecRegistry(pojoCodecRegistry);
My Kotilin Pojo is:
@JsonInclude(JsonInclude.Include.NON_NULL)
class Person {
@JsonProperty("_id")
var personID: String? = null
@JsonProperty("name")
var type: String? = null
@JsonProperty("age")
var age: Int? = null
}
I am able to get a response but the response is not as expected, i.e. it is
{
"persons": [
{
"ID": "personId1"
},
{
"ID": "personId2"
},
{
"ID": "personId3"
}
}
Each person object only shows some ID field rather than the fields in my POJO that I am expecting.
What am I missing here? Do I need to define a custom codec for my Pojo? I am unsure as first time using this mongo library.
答案1
得分: 3
以下是一些工作中的代码,您可以看到我写入数据库并读取数据。
在您的问题中有几件事情不太清楚,这可能可以解释为什么您的尝试没有成功,或者我可能误解了您的需求。
Person
类
Person
是一个 POJO - 对于这个,您可能不希望使用一个普通的 class
。在我创建的方式中,构造 Person
很麻烦 - 我不得不创建一个小的辅助方法,因为您的类中没有构造函数:
private static Person makePerson(String id, String type, int age) {
Person p = new Person();
p.setPersonID(id);
p.setType(type);
p.setAge(age);
return p;
}
然而,如果您进行一些小的修改并使用 data class
,那么这将隐式地为您提供一个构造函数、toString()
和 hashCode()
:
@JsonInclude(JsonInclude.Include.NON_NULL)
data class Person ( //<< round brackets
@JsonProperty("_id")
var personID: String? = null, //<< comma
@JsonProperty("name")
var type: String? = null,
@JsonProperty("age")
var age: Int? = null,
)
编解码器设置
我认为您的编解码器设置方式不正确(如果缺少编解码器,您将收到启动错误)。请查看我的工作代码。
您的预期输出是什么?
您说它与预期不符,是因为缺少了年龄和姓名/类型字段吗?字段名称也是“ID”,您想要什么?personID
、_id
还是 ID
?
您现在的输出是如何实现的?
您没有说明如何提取和显示 JSON 数据,但鉴于您使用的注解(@JsonProperty
),您必须使用 Jackson,我在我的代码示例中包括了它。您提到的快速入门指南谈到了 @BsonProperty
- 这是用于数据库中的字段命名的不同目的,而 @JsonProperty
用于 JSON 中的字段命名。
示例代码
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mongodb.ConnectionString;
import com.mongodb.MongoClientSettings;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.codecs.configuration.CodecRegistry;
import org.bson.codecs.pojo.PojoCodecProvider;
import java.util.ArrayList;
import java.util.List;
import static org.bson.codecs.configuration.CodecRegistries.fromProviders;
import static org.bson.codecs.configuration.CodecRegistries.fromRegistries;
public class Test {
public static void main(String[] args) {
ConnectionString connectionString = new ConnectionString("mongodb://127.0.0.1:27017");
CodecRegistry pojoCodecRegistry = fromProviders(PojoCodecProvider.builder().automatic(true).build());
CodecRegistry codecRegistry = fromRegistries(MongoClientSettings.getDefaultCodecRegistry(), pojoCodecRegistry);
MongoClientSettings clientSettings = MongoClientSettings.builder()
.applyConnectionString(connectionString)
.codecRegistry(codecRegistry)
.build();
try (MongoClient mongoClient = MongoClients.create(clientSettings)) {
MongoDatabase database = mongoClient.getDatabase("person");
MongoCollection<Person> collection = database.getCollection("personCollection", Person.class);
List<Person> persons = new ArrayList<>();
persons.add(makePerson("personId1", "Lesley", 10));
persons.add(makePerson("personId2", "Bob", 20));
persons.add(makePerson("personId3", "Jane", 30));
collection.insertMany(persons);
List<Person> persons2 = collection.find().into(new ArrayList<Person>());
ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(persons2));
} catch (JsonProcessingException e) {
throw a RuntimeException(e);
}
}
private static Person makePerson(String id, String type, int age) {
Person p = new Person();
p.setPersonID(id);
p.setType(type);
p.setAge(age);
return p;
}
}
输出是:
[ {
"_id" : "personId1",
"name" : "Lesley",
"age" : 10
}, {
"_id" : "personId2",
"name" : "Bob",
"age" : 20
}, {
"_id" : "personId3",
"name" : "Jane",
"age" : 30
} ]
我使用的依赖项如下:
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-sync</artifactId>
<version>4.8.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.14.0</version>
</dependency>
英文:
Below is some working code where you can see that I write to the DB and read back data.
Several things are not clear in your question which may either explain why your attempt did not work, or I have misunderstood your requirement.
Person
class
Person
is a POJO - for this you probably don't want to use a straight class
. In the way created it is awkward to construct the Person
- I had to create a little helper method as there is no constructor in your class:
private static Person makePerson(String id, String type, int age) {
Person p = new Person();
p.setPersonID(id);
p.setType(type);
p.setAge(age);
return p;
}
Whereas, if you make a few small alterations and use a data class
then this implicitly gives you a constructor, toString()
, hashCode()
:
@JsonInclude(JsonInclude.Include.NON_NULL)
data class Person ( //<< round brackets
@JsonProperty("_id")
var personID: String? = null, //<< comma
@JsonProperty("name")
var type: String? = null,
@JsonProperty("age")
var age: Int? = null,
)
Codec setup
I don't think you have your Codecs setup in the right way. (If a Codec is missing you will get a startup error.). Observe my working code.
What is your intended output?
You say it is "not as expected", is it that it is missing the age and name/type field? The field name is "ID" too, what do you want? personID
, _id
or ID
?
How is your output implemented now?
How are you extracting and displaying the data in JSON - you don't say but given the annotations you use (@JsonProperty
), you must be using Jackson, I have included that in my code sample. The Quick Start Guide you refer to talks about @BsonProperty
- this is for a different purpose - for how to name the fields in the database, where as @JsonProperty
is for naming in JSON.
Specimen code
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mongodb.ConnectionString;
import com.mongodb.MongoClientSettings;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.codecs.configuration.CodecRegistry;
import org.bson.codecs.pojo.PojoCodecProvider;
import java.util.ArrayList;
import java.util.List;
import static org.bson.codecs.configuration.CodecRegistries.fromProviders;
import static org.bson.codecs.configuration.CodecRegistries.fromRegistries;
public class Test {
public static void main(String[] args) {
ConnectionString connectionString = new ConnectionString("mongodb://127.0.0.1:27017");
CodecRegistry pojoCodecRegistry = fromProviders(PojoCodecProvider.builder().automatic(true).build());
CodecRegistry codecRegistry = fromRegistries(MongoClientSettings.getDefaultCodecRegistry(), pojoCodecRegistry);
MongoClientSettings clientSettings = MongoClientSettings.builder()
.applyConnectionString(connectionString)
.codecRegistry(codecRegistry)
.build();
try (MongoClient mongoClient = MongoClients.create(clientSettings)) {
MongoDatabase database = mongoClient.getDatabase("person");
MongoCollection<Person> collection = database.getCollection("personCollection", Person.class);
List<Person> persons = new ArrayList<>();
persons.add(makePerson("personId1", "Lesley", 10));
persons.add(makePerson("personId2", "Bob", 20));
persons.add(makePerson("personId3", "Jane", 30));
collection.insertMany(persons);
List<Person> persons2 = collection.find().into(new ArrayList<Person>());
ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(persons2));
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
private static Person makePerson(String id, String type, int age) {
Person p = new Person();
p.setPersonID(id);
p.setType(type);
p.setAge(age);
return p;
}
}
And the output is:
[ {
"_id" : "personId1",
"name" : "Lesley",
"age" : 10
}, {
"_id" : "personId2",
"name" : "Bob",
"age" : 20
}, {
"_id" : "personId3",
"name" : "Jane",
"age" : 30
} ]
And the dependencies I used:
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-sync</artifactId>
<version>4.8.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.14.0</version>
</dependency>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论