1. Översikt
I den här handledningen ska vi lära oss hur man implementerar ett sekventiellt, automatiskt genererat fält för MongoDB i Spring Boot.
När vi använder MongoDB som databas för en Spring Boot-applikation kan vi inte använda @GeneratedValue anteckning i våra modeller eftersom den inte är tillgänglig. Därför behöver vi en metod för att producera samma effekt som vi kommer att ha om vi använder JPA och en SQL-databas.
Den allmänna lösningen på detta problem är enkel. Vi skapar en samling (tabell) som lagrar den genererade sekvensen för andra samlingar. Under skapandet av en ny post kommer vi att använda den för att hämta nästa värde.
2. Beroenden
Låt oss lägga till följande spring-boot starters till vår pom.xml :
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<versionId>2.2.2.RELEASE</versionId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
<versionId>2.2.2.RELEASE</versionId>
</dependency>
</dependencies>
Den senaste versionen för beroenden hanteras av spring-boot-starter-parent .
3. Samlingar
Som diskuteras i översikten skapar vi en samling som lagrar den automatiskt inkrementerade sekvensen för andra samlingar. Vi kallar den här samlingen database_sequences. Den kan skapas med antingen mongo skal eller MongoDB Compass. Låt oss skapa en motsvarande modellklass:
@Document(collection = "database_sequences")
public class DatabaseSequence {
@Id
private String id;
private long seq;
//getters and setters omitted
}
Låt oss sedan skapa en användare samling och ett motsvarande modellobjekt som lagrar information om personer som använder vårt system:
@Document(collection = "users")
public class User {
@Transient
public static final String SEQUENCE_NAME = "users_sequence";
@Id
private long id;
private String email;
//getters and setters omitted
}
I Användare modell skapad ovan har vi lagt till ett statiskt fält SEQUENCE_NAME, vilket är en unik referens till den automatiskt inkrementerade sekvensen för användarna samling.
Vi kommenterar det också med @Transient för att förhindra att den kvarstår tillsammans med andra egenskaper hos modellen.
4. Skapa en ny post
Hittills har vi skapat de kollektioner och modeller som krävs. Nu skapar vi en tjänst som genererar det automatiskt ökade värdet som kan användas som id för våra enheter.
Låt oss skapa en SequenceGeneratorService som har generateSequence() :
public long generateSequence(String seqName) {
DatabaseSequence counter = mongoOperations.findAndModify(query(where("_id").is(seqName)),
new Update().inc("seq",1), options().returnNew(true).upsert(true),
DatabaseSequence.class);
return !Objects.isNull(counter) ? counter.getSeq() : 1;
}
Nu kan vi använda generateSequence() medan du skapar en ny post:
User user = new User();
user.setId(sequenceGenerator.generateSequence(User.SEQUENCE_NAME));
user.setEmail("[email protected]");
userRepository.save(user);
För att lista alla användare använder vi UserRepository :
List<User> storedUsers = userRepository.findAll();
storedUsers.forEach(System.out::println);
Som det är nu måste vi ställa in id-fältet varje gång vi skapar en ny instans av vår modell. Vi kan kringgå denna process genom att skapa en lyssnare för Spring Data MongoDB livscykelhändelser.
För att göra det skapar vi en UserModelListener som utökar AbstractMongoEventListener
@Override
public void onBeforeConvert(BeforeConvertEvent<User> event) {
if (event.getSource().getId() < 1) {
event.getSource().setId(sequenceGenerator.generateSequence(User.SEQUENCE_NAME));
}
}
Nu, varje gång vi sparar en ny användare, id kommer att ställas in automatiskt.