Overview
在本指南中,您可以学习;了解如何使用Java Reactive Streams驾驶员来存储和检索由普通旧Java对象 (POJO) 建模的数据。 POJO 通常用于数据封装,这是将业务逻辑与数据表示分离的做法。
本指南介绍如何执行以下任务:
配置驱动程序,对 POJO 进行序列化和反序列化
使用 POJO 建模的数据执行增删改查操作
重要
本指南使用自定义Subscriber实现,如《自定义订阅服务器实现示例》指南中所述。
POJO 示例
本指南中的示例使用 Person 和 Address POJO 类对名为 people的示例集合中的文档进行建模。
Person 类存储人员的姓名、年龄和解决。该类具有以下定义:
import org.bson.types.ObjectId; public final class Person { private ObjectId id; private String name; private int age; private Address address; public Person() {} public Person(final String name, final int age, final Address address) { this.name = name; this.age = age; this.address = address; } public ObjectId getId() { return id; } public void setId(final ObjectId id) { this.id = id; } public String getName() { return name; } public void setName(final String name) { this.name = name; } public int getAge() { return age; } public void setAge(final int age) { this.age = age; } public Address getAddress() { return address; } public void setAddress(final Address address) { this.address = address; } public String toString() { return "Person{" + "id='" + id + "'" + ", name='" + name + "'" + ", age=" + age + ", address=" + address + "}"; } }
Address 类存储街道、城市和邮政编码。该类具有以下定义:
public final class Address { private String street; private String city; private String zip; public Address() {} public Address(final String street, final String city, final String zip) { this.street = street; this.city = city; this.zip = zip; } public String getStreet() { return street; } public void setStreet(final String street) { this.street = street; } public String getCity() { return city; } public void setCity(final String city) { this.city = city; } public String getZip() { return zip; } public void setZip(final String zip) { this.zip = zip; } public String toString() { return "Address{" + "street='" + street + "'" + ", city='" + city + "'" + ", zip='" + zip + "'" + "}"; } }
定义 POJO 类时,请确保满足以下要求:
POJO 类不能实现接口或继承框架中的类。
包括要存储和检索数据的所有字段,并确保它们没有标记为
static或transient。如果您按照 JavaBean 命名约定包含公共 getter 或 setter 方法,则驾驶员在序列化或反序列化数据时会调用这些方法。如果省略公共字段的 getter 或 setter 方法,驾驶员将直接访问或分配它们。
为 POJO 配置驱动程序
在将 POJO 与Java Reactive Streams驾驶员一起使用之前,必须通过创建自定义 CodecRegistry 将其配置为序列化和反序列化 POJO。以下步骤说明如何创建 CodecRegistry 并将其应用客户端、数据库或集合。
应用 CodecRegistry。
配置 MongoClient、MongoDatabase 或 MongoCollection实例以使用自定义 CodecRegistry。您可以通过以下方式之一设立编解码器注册表:
在
MongoClient上设置CodecRegistry:MongoClientSettings settings = MongoClientSettings.builder() .codecRegistry(pojoCodecRegistry) .build(); 在
MongoDatabase上设置CodecRegistry:MongoDatabase database = mongoClient.getDatabase("mydb").withCodecRegistry(pojoCodecRegistry); 在
MongoCollection上设置CodecRegistry:MongoCollection<org.bson.Document> rawCollection = database.getCollection("people").withCodecRegistry(pojoCodecRegistry);
执行 CRUD 操作
将驾驶员配置为使用 Person POJO 后,您可以对 POJO 建模的数据执行增删改查操作。
Insert Data
编解码器注册表会自动为未知类创建 POJO Codec,允许您开箱即用 POJO,无需额外的配置。
要将单个 Person 插入集合中,请调用 insertOne() 方法并订阅结果。以下示例将名为 ada 的 Person实例插入到 people集合中:
Person ada = new Person("Ada Byron", 20, new Address("St James Square", "London", "W1")); collection.insertOne(ada).subscribe(new OperationSubscriber<InsertOneResult>());
要插入多个 Person 实例,请调用 insertMany() 方法并传递实例列表,如以下示例所示:
List<Person> people = asList( new Person("Charles Babbage", 45, new Address("5 Devonshire Street", "London", "W11")), new Person("Alan Turing", 28, new Address("Bletchley Hall", "Bletchley Park", "MK12")), new Person("Timothy Berners-Lee", 61, new Address("Colehill", "Wimborne", null)) ); collection.insertMany(people).subscribe(new OperationSubscriber<InsertManyResult>());
查询数据
要查询集合,请使用 find() 方法。您可以将过滤对象传递给 find() 方法,以检索与特定条件匹配的文档。驾驶员提供了可用于创建过滤对象的 Filters 辅助方法。
重要
查询 POJO 时,必须查询文档字段名称,而不是 POJO属性名称。默认下,它们是相同的,但可以更改驾驶员映射 POJO属性名称的方式。
Retrieve One
要检索与过滤匹配的第一个 Person实例,请对 find() 操作的结果调用 first() 方法。
以下示例检索 address.city字段值为 "Wimborne" 的第一个 Person实例:
collection.find(eq("address.city", "Wimborne")) .first() .subscribe(new PrintToStringSubscriber<>());
Person{id='...', name='Timothy Berners-Lee', age=61, address=Address{street='Colehill', city='Wimborne', zip='null'}}
检索多个
要检索与过滤匹配的所有 Person 实例,请调用 find() 方法并订阅结果。
以下示例检索 age字段值大于 30 的每个 Person实例:
collection.find(gt("age", 30)).subscribe(new PrintToStringSubscriber<>());
Person{id='...', name='Charles Babbage', age=45, address=Address{street='5 Devonshire Street', city='London', zip='W11'}} Person{id='...', name='Timothy Berners-Lee', age=61, address=Address{street='Colehill', city='Wimborne', zip='null'}}
更新数据
要更新集合中的文档,请使用 updateOne() 和 updateMany() 方法。将以下参数传递给这些方法:
指定要更新的一个或多个文档的筛选器对象。
更新方法返回 UpdateResult 类型,其中提供有关操作的信息,包括修改的文档数。
updateOne
要更新与过滤匹配的单个 Person实例,请使用 updateOne() 方法。
以下示例通过将 age字段值设置为 23 并将 name字段值设置为 "Ada Lovelace" 来更新名为 "Ada Byron" 的 Person:
collection.updateOne( eq("name", "Ada Byron"), combine(set("age", 23), set("name", "Ada Lovelace")) ).subscribe(new OperationSubscriber<>());
更新多个
要更新与筛选器匹配的所有Person实例,请使用updateMany()方法。
以下示例将所有具有非空 zip 值的 Person 实例的 zip字段值设置为 null:
collection.updateMany(not(eq("zip", null)), set("zip", null)) .subscribe(new OperationSubscriber<>());
replaceOne
要完全替换现有的 Person实例,请使用 replaceOne() 方法。
以下示例将 name字段值为 "Ada Lovelace" 的 Person实例替换为 ada 变量引用的 Person:
collection.replaceOne(eq("name", "Ada Lovelace"), ada) .subscribe(new OperationSubscriber<>());
删除数据
要从集合中删除文档,请使用 deleteOne() 和 deleteMany() 方法。传递过滤对象以匹配要删除的文档或多个文档。
删除方法返回DeleteResult类型,其中提供有关操作的信息,包括删除的文档数。
deleteOne
要删除与过滤器匹配的单个Person ,请使用deleteOne()方法。
以下示例删除一个 address.city字段值为 "Wimborne" 的 Person实例:
collection.deleteOne(eq("address.city", "Wimborne")) .subscribe(new OperationSubscriber<>());
删除多个
要删除与过滤匹配的所有 Person 实例,请使用 deleteMany() 方法。
以下示例删除 address.city字段值为 "London" 的所有 Person 实例:
collection.deleteMany(eq("address.city", "London")) .subscribe(new OperationSubscriber<>());
更多信息
要学习;了解有关本指南中提及的增删改查操作的更多信息,请参阅增删改查操作部分。
API 文档
要学习;了解有关本指南中提到的方法和类的更多信息,请参阅以下API文档: