拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 带有Spring 数据的MongoDB 组合键

带有Spring 数据的MongoDB 组合键

白鹭 - 2022-06-25 2149 0 2

一、简介

在本教程中,我们将在Spring Data MongoDB 应用程序中创建复合键。我们将了解不同的策略以及如何配置它们。

2. 什么是复合键以及何时使用它

复合键是文档中唯一标识它的属性的组合。使用复合主键并不比使用单个自动生成的属性更好或更差。我们甚至可以将这些方法与唯一索引结合起来。

通常,没有单一的属性能够唯一地标识一个文档。在这些情况下,我们可以将其留空,MongoDB 将为其“ _id”属性生成一个唯一值。或者,我们可以选择多个属性,当它们组合时,服务于该目的。在这种情况下,我们必须为我们的ID 属性创建一个自定义类来保存所有这些属性。让我们看看这是如何工作的。

3. 使用@Id注解创建复合键

@Id注释可用于注释自定义类型的属性,从而完全控制其生成。ID 类的唯一要求是我们覆盖equals()hashCode()并具有默认的无参数构造函数。

在我们的第一个示例中,我们将为活动门票创建一个文档。它的ID 将是venuedate属性的组合。让我们从我们的ID 类开始:

public class TicketId {
private String venue;
private String date;
// getters and setters
// override hashCode() and equals()
}

由于无参数构造函数是隐式的,而且我们不需要其他构造函数,所以我们不需要编写它。此外,我们将使用String日期来简化示例。接下来,让我们创建我们的Ticket类,并使用@Id注释我们的TicketId属性:

@Document
public class Ticket {
@Id
private TicketId id;
private String event;
// getters and setters
}

对于我们的MongoRepository,我们可以将TicketId指定为ID 类型,这就是所需的全部设置:

public interface TicketRepository extends MongoRepository<Ticket, TicketId> {
}

3.1。测试我们的模型

因此,尝试两次插入具有相同ID 的票证将引发DuplicateKeyException我们可以通过测试来检查:

@Test
public void givenCompositeId_whenDupeInsert_thenExceptionIsThrown() {
TicketId ticketId = new TicketId();
ticketId.setDate("2020-01-01");
ticketId.setVenue("V");
Ticket ticket = new Ticket(ticketId, "Event C");
service.insert(ticket);
assertThrows(DuplicateKeyException.class, () -> {
service.insert(ticket);
});
}

这可以确保我们的密钥正常工作。

3.2.按ID 查找

由于我们将TicketId定义为存储库中的ID 类,我们仍然可以使用默认的findById()方法。让我们编写一个测试来看看它的实际效果:

@Test
public void givenCompositeId_whenSearchingByIdObject_thenFound() {
TicketId ticketId = new TicketId();
ticketId.setDate("2020-01-01");
ticketId.setVenue("Venue B");
service.insert(new Ticket(ticketId, "Event B"));
Optional<Ticket> optionalTicket = ticketRepository.findById(ticketId);
assertThat(optionalTicket.isPresent());
Ticket savedTicket = optionalTicket.get();
assertEquals(savedTicket.getId(), ticketId);
}

当我们想要绝对控制我们的ID 属性时,我们应该使用这种方法。同样,这将确保我们的ID 对像中的属性不能被修改。一个缺点是我们丢失了MongoDB 生成的ID,可读性较差。但是,例如,更易于在链接中使用。

4. 警告

当使用嵌套对像作为ID 时,属性的顺序很重要。使用我们的存储库时这通常不是问题,因为Java 对象总是以相同的顺序构造的。但是,如果我们更改TicketId类中字段的顺序,我们可以插入另一个具有相同值的文档。例如,这些对像被认为是不同的:

{
"id": {
"venue":"Venue A",
"date": "2023-05-27"
},
"event": "Event 1"
}

之后,如果我们更改TicketId中的字段顺序,我们将能够插入相同的值。不会抛出异常:

{
"id": {
"date": "2023-05-27",
"venue":"Venue A"
},
"event": "Event 1"
}

如果我们在Ticket类的属性上使用唯一索引而不是ID 类,则不会发生这种情况。换句话说,它只发生在嵌套对像上。

5. 结论

在本文中,我们看到了为MongoDB 文档创建复合键的优缺点。以及使用简单用例实现它们所需的配置。但是,我们还了解到一个需要注意的重要警告。


0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *