NoSQL数据库与关系型数据库的不同之处在于允许更复杂的结构,而无需传统的一对多或一对一关系。相反,NoSQL数据库利用灵活的类型,如数组或子文档,有效地在单个文档内存储相关数据。这种灵活性使开发人员能够设计适合其应用程序查询和性能需求的模型。
Jakarta NoSQL是一个简化与NoSQL数据库(包括MongoDB)交互的Java框架。它提供了注解,用于确定数据的映射和存储方式,使开发人员能够控制嵌入对象是分组还是以扁平方式存储。
在使用MongoDB和Jakarta NoSQL时,其中一个关键考虑因素是如何构造文档结构。在扁平结构和分组结构之间进行选择会影响数据的存储、查询和检索方式。在本文中,我们将使用一个实际示例来探讨这两种方法。
Jakarta NoSQL和产品实体
为了理解扁平结构和分组结构,让我们首先介绍Product
实体并看看Jakarta NoSQL注解的工作方式:
public class Product {
ObjectIdConverter.class) (
private String id;
private String name;
private Manufacturer manufacturer;
private List<String> tags;
private Set<Category> categories;
Product(String name, Manufacturer manufacturer, List<String> tags, Set<Category> categories) {
this.name = name;
this.manufacturer = manufacturer;
this.tags = tags;
this.categories = categories;
}
public static ProductBuilder builder() {
return new ProductBuilder();
}
}
现在,让我们探讨如何根据Jakarta NoSQL注解,manufacturer
字段可以以不同的方式存储。
理解分组结构和扁平结构
分组结构
分组结构将相关信息组织成文档中的不同对象。这种方法可以提高可读性,并支持更清晰的领域建模实践。Jakarta NoSQL通过使用@Embeddable(Embeddable.EmbeddableType.GROUPING)
实现这一点。
示例:
{
"_id": { "$oid": "67b264520abd020ec0eb9a4c" },
"categories": [
{ "name": "Computers", "description": "All computers" },
{ "name": "Electronics", "description": "All electronics" }
],
"manufacturer": {
"address": "One Infinite Loop Cupertino, CA 95014",
"name": "Apple",
"contactNumber": "+1-408-996-1010"
},
"name": "MacBook Pro",
"tags": ["smartphone", "tablet", "laptop"]
}
在这里,制造商被分组到一个单独的子对象中,而不是将其属性放在顶层。
Embeddable.EmbeddableType.GROUPING) (
public record Manufacturer( String name, String address, String contactNumber) {}
平面结构
保持相关信息在同一文档内,直接嵌入列表或嵌套字段。Jakarta NoSQL通过使用@Embeddable(Embeddable.EmbeddableType.FLAT)
实现这一点。当您希望快速访问所有细节而无需复杂查询时,这种方法很有益。
示例:
{
"_id": { "$oid": "67b22d20c921154b0223b27b" },
"address": "One Infinite Loop Cupertino, CA 95014",
"categories": [
{ "name": "Electronics", "description": "All electronics" },
{ "name": "Computers", "description": "All computers" }
],
"contactNumber": "+1-408-996-1010",
"name": "Apple",
"tags": ["smartphone", "tablet", "laptop"]
}
这种方法直接存储制造商细节在文档中,而不是将它们分组到单独的字段中。
Embeddable.EmbeddableType.FLAT) (
public record Manufacturer( String name, String address, String contactNumber) {}
Jakarta NoSQL中的示例用法
以下代码片段展示了Jakarta NoSQL如何集成这些结构:
public class App {
public static void main(String[] args) {
var faker = new Faker();
try (SeContainer container = SeContainerInitializer.newInstance().initialize()) {
var template = container.select(DocumentTemplate.class).get();
var electronicsCategory = new Category("Electronics", "All electronics");
var computerCategory = new Category("Computers", "All computers");
var tags = List.of("smartphone", "tablet", "laptop");
var manufacturer = new Manufacturer("Apple", "One Infinite Loop Cupertino, CA 95014", "+1-408-996-1010");
Product macBookPro = Product.builder().categories(Set.of(electronicsCategory, computerCategory))
.manufacturer(manufacturer)
.name("MacBook Pro")
.tags(tags)
.build();
Product product = template.insert(macBookPro);
System.out.println("Product saved: " + product);
}
}
}
选择正确的方法
- 当您需要一个简单的文档布局,所有属性都在同一级别时,请使用平面结构。
- 当将相关数据组织成逻辑子对象以提高可读性和可维护性时,请使用分组结构。
结论
Jakarta NoSQL提供了使用@Embeddable(Embeddable.EmbeddableType)
来灵活构建MongoDB文档的方式。选择扁平或分组结构取决于您的数据访问模式和建模偏好。了解这些方法可以实现高效的数据库设计,使查询更有效,同时保持领域模型清晰和结构良好。
完整的代码,请访问GitHub存储库。
视频
Source:
https://dzone.com/articles/handling-embedded-data-in-nosql-with-java