Cách tạo _id trong MongoDB

Theo mặc định, trình điều khiển Java MongoDB tạo ID thuộc loại ObjectId. Đôi khi, chúng tôi có thể muốn sử dụng một loại dữ liệu khác làm mã định danh duy nhất của một đối tượng, chẳng hạn như UUID. Tuy nhiên, trình điều khiển Java MongoDB không thể tự động tạo UUID

Trong hướng dẫn này, chúng ta sẽ xem xét ba cách để tạo UUID với trình điều khiển Java MongoDB và Spring Data MongoDB

2. Điểm thông dụng

Khá hiếm khi một ứng dụng chỉ quản lý một loại dữ liệu. Để đơn giản hóa việc quản lý ID trong cơ sở dữ liệu MongoDB của chúng tôi, việc triển khai một lớp trừu tượng sẽ xác định ID của tất cả các lớp Tài liệu của chúng tôi sẽ dễ dàng hơn

public abstract class UuidIdentifiedEntity {

    @Id   
    protected UUID id;    

    public void setId(UUID id) {

        if (this.id != null) {
            throw new UnsupportedOperationException("ID is already defined");
        }

        this.id = id;
    }

    // Getter
}

Đối với các ví dụ trong hướng dẫn này, chúng tôi sẽ giả sử rằng tất cả các lớp vẫn tồn tại trong cơ sở dữ liệu MongoDB được kế thừa từ lớp này

3. Định cấu hình hỗ trợ UUID

Để cho phép lưu trữ UUID trong MongoDB, chúng ta phải định cấu hình trình điều khiển. Cấu hình này rất đơn giản và chỉ cho trình điều khiển biết cách lưu trữ UUID trong cơ sở dữ liệu. Chúng tôi phải xử lý việc này cẩn thận nếu một số ứng dụng sử dụng cùng một cơ sở dữ liệu

Tất cả những gì chúng ta phải làm là chỉ định tham số uuidRepresentation trong ứng dụng khách MongoDB của chúng ta khi khởi động

@Bean
public MongoClient mongo() throws Exception {
    ConnectionString connectionString = new ConnectionString("mongodb://localhost:27017/test");
    MongoClientSettings mongoClientSettings = MongoClientSettings.builder()
      .uuidRepresentation(UuidRepresentation.STANDARD)
      .applyConnectionString(connectionString).build();
    return MongoClients.create(mongoClientSettings);
}

Nếu chúng ta sử dụng Spring Boot, chúng ta có thể chỉ định tham số này trong ứng dụng của mình. tệp thuộc tính

spring.data.mongodb.uuid-representation=standard

4. Sử dụng Sự kiện Vòng đời

Phương pháp đầu tiên để xử lý việc tạo UUID là sử dụng các sự kiện vòng đời của Spring. Với các thực thể MongoDB, chúng tôi không thể sử dụng các chú thích JPA @PrePersist, v.v. Do đó, chúng ta phải triển khai các lớp lắng nghe sự kiện đã đăng ký trong ApplicationContext. Để làm như vậy, các lớp của chúng ta phải mở rộng lớp AbstractMongoEventListener của Spring

public class UuidIdentifiedEntityEventListener extends AbstractMongoEventListener {
    
    @Override
    public void onBeforeConvert(BeforeConvertEvent event) {
        
        super.onBeforeConvert(event);
        UuidIdentifiedEntity entity = event.getSource();
        
        if (entity.getId() == null) {
            entity.setId(UUID.randomUUID());
        } 
    }    
}

Trong trường hợp này, chúng tôi đang sử dụng sự kiện OnB BeforeConvert, được kích hoạt trước khi Spring chuyển đổi đối tượng Java của chúng tôi thành đối tượng Tài liệu và gửi nó tới trình điều khiển MongoDB

Nhập sự kiện của chúng tôi để bắt lớp UuidIdentifiedEntity cho phép xử lý tất cả các lớp con của siêu kiểu trừu tượng này. Spring sẽ gọi mã của chúng ta ngay khi một đối tượng sử dụng UUID làm ID được chuyển đổi

Chúng ta phải lưu ý rằng, Spring ủy quyền xử lý sự kiện cho một TaskExecutor có thể không đồng bộ. Spring không đảm bảo rằng sự kiện được xử lý trước khi đối tượng được chuyển đổi hiệu quả. Phương pháp này không được khuyến khích trong trường hợp TaskExecutor của bạn không đồng bộ vì ID có thể được tạo sau khi đối tượng đã được chuyển đổi, dẫn đến Ngoại lệ

UnlimitedDataAccessApiUsageException. Không thể tự động tạo id của loại java. sử dụng. UUID cho thực thể

Chúng ta có thể đăng ký trình xử lý sự kiện trong ApplicationContext bằng cách chú thích nó bằng @Component hoặc bằng cách tạo nó trong lớp @Configuration

@Bean
public UuidIdentifiedEntityEventListener uuidIdentifiedEntityEventListener() {
    return new UuidIdentifiedEntityEventListener();
}

5. Sử dụng gọi lại thực thể

Cơ sở hạ tầng mùa xuân cung cấp các hook để thực thi mã tùy chỉnh tại một số điểm trong vòng đời của một thực thể. Chúng được gọi là EntityCallbacks và chúng ta có thể sử dụng chúng trong trường hợp của mình để tạo UUID trước khi đối tượng được duy trì trong cơ sở dữ liệu

Không giống như phương pháp lắng nghe sự kiện đã thấy trước đây, các cuộc gọi lại đảm bảo rằng việc thực thi của chúng là đồng bộ và mã sẽ chạy tại điểm dự kiến ​​trong vòng đời của đối tượng

Dữ liệu mùa xuân MongoDB cung cấp một tập hợp các cuộc gọi lại mà chúng ta có thể sử dụng trong ứng dụng của mình. Trong trường hợp của chúng tôi, chúng tôi sẽ sử dụng cùng một sự kiện như trước đây. Gọi lại có thể được cung cấp trực tiếp trong lớp @Configuration

@Bean
public BeforeConvertCallback beforeSaveCallback() {
        
    return (entity, collection) -> {
          
        if (entity.getId() == null) {
            entity.setId(UUID.randomUUID());
        }
        return entity;
    };
}

Chúng tôi cũng có thể sử dụng Thành phần triển khai giao diện BeforeConvertCallback

6. Sử dụng kho lưu trữ tùy chỉnh

Dữ liệu mùa xuân MongoDB cung cấp phương pháp thứ ba để đạt được mục tiêu của chúng tôi. sử dụng triển khai kho lưu trữ tùy chỉnh. Thông thường, chúng ta chỉ cần khai báo một giao diện kế thừa từ MongoRepository, sau đó Spring sẽ xử lý các mã liên quan đến kho lưu trữ

Nếu chúng tôi muốn thay đổi cách Spring Data xử lý các đối tượng của mình, chúng tôi có thể xác định mã tùy chỉnh mà Spring sẽ thực thi ở cấp độ kho lưu trữ. Để làm như vậy, trước tiên chúng ta phải xác định một giao diện mở rộng MongoRepository

@NoRepositoryBean
public interface CustomMongoRepository extends MongoRepository { }

Chú thích @NoRepositoryBean ngăn Spring tạo đoạn mã thông thường được liên kết với MongoRepository. Giao diện này buộc sử dụng UUID làm loại ID trong các đối tượng

Sau đó, chúng ta phải tạo một lớp kho lưu trữ sẽ xác định hành vi cần thiết để xử lý các UUID của chúng ta

public class CustomMongoRepositoryImpl 
  extends SimpleMongoRepository implements CustomMongoRepository

Trong kho lưu trữ này, chúng tôi sẽ phải bắt tất cả các cuộc gọi phương thức mà chúng tôi cần tạo ID bằng cách ghi đè các phương thức có liên quan của SimpleMongoRepository. Các phương thức đó là save() và insert() trong trường hợp của chúng ta

________số 8

Cuối cùng, chúng ta cần yêu cầu Spring sử dụng lớp tùy chỉnh của mình làm triển khai kho lưu trữ thay vì triển khai mặc định. Chúng tôi làm điều đó trong lớp @Configuration

@EnableMongoRepositories(basePackages = "com.baeldung.repository", repositoryBaseClass = CustomMongoRepositoryImpl.class)

Sau đó, chúng tôi có thể khai báo các kho lưu trữ của mình như bình thường mà không có thay đổi nào

@Bean
public MongoClient mongo() throws Exception {
    ConnectionString connectionString = new ConnectionString("mongodb://localhost:27017/test");
    MongoClientSettings mongoClientSettings = MongoClientSettings.builder()
      .uuidRepresentation(UuidRepresentation.STANDARD)
      .applyConnectionString(connectionString).build();
    return MongoClients.create(mongoClientSettings);
}
0

7. Sự kết luận

Trong bài viết này, chúng ta đã thấy ba cách để triển khai UUID làm ID của đối tượng MongoDB với Spring Data MongoDB

_id trong MongoDB là gì?

Theo mặc định, MongoDB tạo một chỉ mục duy nhất trên trường _id trong quá trình tạo bộ sưu tập. Trường _id luôn là trường đầu tiên trong tài liệu. Nếu máy chủ nhận tài liệu không có trường _id trước thì máy chủ sẽ chuyển trường này về đầu

Làm cách nào để tự động tạo id trong MongoDB?

Hãy sử dụng các bước sau để tạo trình tự tăng tự động MongoDB cho id mục. .
Tạo bộ sưu tập mẫu
Chèn một tài liệu vào một bộ sưu tập
Chèn bản ghi vào bộ sưu tập
Trình tự cơ sở dữ liệu
Tạo một hàm JavaScript
Sử dụng chức năng JavaScript
Xem đã chèn bản ghi từ bộ sưu tập cửa hàng

_id có bắt buộc trong MongoDB không?

Một trường bắt buộc trong mọi tài liệu MongoDB . Trường _id phải có một giá trị duy nhất. Bạn có thể coi trường _id là khóa chính của tài liệu. Nếu bạn tạo một tài liệu mới không có trường _id, MongoDB sẽ tự động tạo trường này và gán một ObjectId BSON duy nhất.

Kiểu dữ liệu của _id là gì?

_id là khóa mặc định được tạo để nhận dạng duy nhất từng tài liệu trong bộ sưu tập. ObjectId 12 byte , là một giá trị chuỗi thập lục phân bao gồm. giá trị 4 byte biểu thị số giây kể từ kỷ nguyên Unix, mã định danh máy 3 byte, id tiến trình 2 byte và.