MongoDB
 sql >> Cơ Sở Dữ Liệu >  >> NoSQL >> MongoDB

Giới thiệu về Spring Data MongoDB

1. Tổng quan

Bài viết này sẽ là phần giới thiệu nhanh và thiết thực về Spring Data MongoDB.

Chúng ta sẽ xem xét những điều cơ bản bằng cách sử dụng cả MongoTemplate cũng như MongoRepository , với các ví dụ thực tế để minh họa từng thao tác.


Đọc thêm:

Hỗ trợ không gian địa lý trong MongoDB

Hãy xem cách lưu trữ, lập chỉ mục và tìm kiếm dữ liệu không gian địa lý với MongoDBĐọc thêm →

Kiểm tra tích hợp khởi động mùa xuân với MongoDB nhúng

Tìm hiểu cách sử dụng giải pháp MongoDB nhúng của Flapdoodle cùng với Spring Boot để chạy các bài kiểm tra tích hợp MongoDB một cách suôn sẻ. Đọc thêm →

2. MongoTemplate MongoRepository

MongoTemplate tuân theo mẫu mẫu tiêu chuẩn trong Spring và cung cấp một API cơ bản, sẵn sàng hoạt động cho công cụ bền bỉ bên dưới.

Kho lưu trữ tuân theo phương pháp tiếp cận lấy Dữ liệu mùa xuân làm trung tâm và đi kèm với các hoạt động API phức tạp và linh hoạt hơn, dựa trên các mẫu truy cập nổi tiếng trong tất cả các dự án Dữ liệu mùa xuân.

Đối với cả hai, chúng ta cần bắt đầu bằng cách xác định phần phụ thuộc - ví dụ:trong pom.xml , với Maven:

<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-mongodb</artifactId>
    <version>3.0.3.RELEASE</version>
</dependency>

Để kiểm tra xem có phiên bản thư viện mới nào đã được phát hành hay không, hãy theo dõi các bản phát hành tại đây.

3. Cấu hình cho MongoTemplate

3.1. Cấu hình XML

Hãy bắt đầu với cấu hình XML đơn giản cho mẫu Mongo:

<mongo:mongo-client id="mongoClient" host="localhost" />
<mongo:db-factory id="mongoDbFactory" dbname="test" mongo-client-ref="mongoClient" />

Trước tiên, chúng ta cần xác định factory bean chịu trách nhiệm tạo các phiên bản Mongo.

Tiếp theo, chúng ta cần thực sự xác định (và cấu hình) bean mẫu:

<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate"> 
    <constructor-arg ref="mongoDbFactory"/> 
</bean>

Và cuối cùng, chúng ta cần xác định bộ xử lý bài đăng để dịch bất kỳ MongoExceptions nào ném vào @Repository các lớp được chú thích:

<bean class=
  "org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>

3.2. Cấu hình Java

Bây giờ chúng ta hãy tạo một cấu hình tương tự bằng cách sử dụng cấu hình Java bằng cách mở rộng lớp cơ sở cho cấu hình MongoDB AbstractMongoConfiguration :

@Configuration
public class MongoConfig extends AbstractMongoClientConfiguration {
 
    @Override
    protected String getDatabaseName() {
        return "test";
    }
 
    @Override
    public MongoClient mongoClient() {
        ConnectionString connectionString = new ConnectionString("mongodb://localhost:27017/test");
        MongoClientSettings mongoClientSettings = MongoClientSettings.builder()
            .applyConnectionString(connectionString)
            .build();
        
        return MongoClients.create(mongoClientSettings);
    }
 
    @Override
    public Collection getMappingBasePackages() {
        return Collections.singleton("com.baeldung");
    }
}

Lưu ý rằng chúng tôi không cần định nghĩa MongoTemplate bean trong cấu hình trước vì nó đã được xác định trong AbstractMongoClientConfiguration .

Chúng tôi cũng có thể sử dụng cấu hình của mình từ đầu mà không cần mở rộng AbstractMongoClientConfiguration :

@Configuration
public class SimpleMongoConfig {
 
    @Bean
    public MongoClient mongo() {
        ConnectionString connectionString = new ConnectionString("mongodb://localhost:27017/test");
        MongoClientSettings mongoClientSettings = MongoClientSettings.builder()
          .applyConnectionString(connectionString)
          .build();
        
        return MongoClients.create(mongoClientSettings);
    }

    @Bean
    public MongoTemplate mongoTemplate() throws Exception {
        return new MongoTemplate(mongo(), "test");
    }
}

4. Cấu hình cho MongoRepository

4.1. Cấu hình XML

Để sử dụng kho lưu trữ tùy chỉnh (mở rộng MongoRepository ), chúng ta cần tiếp tục cấu hình từ phần 3.1. và thiết lập kho:

<mongo:repositories 
  base-package="com.baeldung.repository" mongo-template-ref="mongoTemplate"/>

4.2. Cấu hình Java

Tương tự, chúng ta sẽ xây dựng trên cấu hình mà chúng ta đã tạo trong phần 3.2. và thêm chú thích mới vào hỗn hợp:

@EnableMongoRepositories(basePackages = "com.baeldung.repository")

4.3. Tạo kho lưu trữ

Sau khi cấu hình, chúng tôi cần tạo một kho lưu trữ - mở rộng MongoRepository hiện có giao diện:

public interface UserRepository extends MongoRepository<User, String> {
    // 
}

Giờ đây, chúng tôi có thể tự động kết nối UserRepository này và sử dụng các hoạt động từ MongoRepository hoặc thêm các thao tác tùy chỉnh.

5. Sử dụng MongoTemplate

5.1. Chèn

Hãy bắt đầu với thao tác chèn cũng như cơ sở dữ liệu trống:

{
}

Bây giờ nếu chúng tôi chèn một người dùng mới:

User user = new User();
user.setName("Jon");
mongoTemplate.insert(user, "user");

cơ sở dữ liệu sẽ trông như thế này:

{
    "_id" : ObjectId("55b4fda5830b550a8c2ca25a"),
    "_class" : "com.baeldung.model.User",
    "name" : "Jon"
}

5.2. Lưu - Chèn

Sự tiết kiệm hoạt động có ngữ nghĩa lưu hoặc cập nhật:nếu có id, nó thực hiện cập nhật và nếu không, nó thực hiện chèn.

Hãy xem ngữ nghĩa đầu tiên - phần chèn.

Đây là trạng thái ban đầu của cơ sở dữ liệu :

{
}

Khi bây giờ chúng ta tiết kiệm người dùng mới:

User user = new User();
user.setName("Albert"); 
mongoTemplate.save(user, "user");

thực thể sẽ được chèn vào cơ sở dữ liệu:

{
    "_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
    "_class" : "com.baeldung.model.User",
    "name" : "Albert"
}

Tiếp theo, chúng ta sẽ xem xét hoạt động tương tự - lưu - với ngữ nghĩa cập nhật.

5.3. Lưu - Cập nhật

Bây giờ chúng ta hãy xem xét lưu với ngữ nghĩa cập nhật, hoạt động trên một thực thể hiện có:

{
    "_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
    "_class" : "com.baeldung.model.User",
    "name" : "Jack"
}

Khi chúng ta tiết kiệm người dùng hiện tại, chúng tôi sẽ cập nhật nó:

user = mongoTemplate.findOne(
  Query.query(Criteria.where("name").is("Jack")), User.class);
user.setName("Jim");
mongoTemplate.save(user, "user");

Cơ sở dữ liệu sẽ giống như sau:

{
    "_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
    "_class" : "com.baeldung.model.User",
    "name" : "Jim"
}

Chúng ta có thể thấy rằng trong ví dụ cụ thể này, lưu sử dụng ngữ nghĩa của update bởi vì chúng tôi sử dụng một đối tượng có _id cho trước .

5.4. UpdateFirst

updateFirst cập nhật tài liệu đầu tiên phù hợp với truy vấn.

Hãy bắt đầu với trạng thái ban đầu của cơ sở dữ liệu:

[
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
        "_class" : "com.baeldung.model.User",
        "name" : "Alex"
    },
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
        "_class" : "com.baeldung.model.User",
        "name" : "Alex"
    }
]

Khi bây giờ chúng tôi chạy updateFirst :

Query query = new Query();
query.addCriteria(Criteria.where("name").is("Alex"));
Update update = new Update();
update.set("name", "James");
mongoTemplate.updateFirst(query, update, User.class);

chỉ mục nhập đầu tiên sẽ được cập nhật:

[
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
        "_class" : "com.baeldung.model.User",
        "name" : "James"
    },
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
        "_class" : "com.baeldung.model.User",
        "name" : "Alex"
    }
]

5.5. UpdateMulti

UpdateMulti cập nhật tất cả các tài liệu phù hợp với truy vấn nhất định.

Đầu tiên, đây là trạng thái của cơ sở dữ liệu trước khi thực hiện updateMulti :

[
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
        "_class" : "com.baeldung.model.User",
        "name" : "Eugen"
    },
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
        "_class" : "com.baeldung.model.User",
        "name" : "Eugen"
    }
]

Bây giờ, hãy chạy updateMulti hoạt động:

Query query = new Query();
query.addCriteria(Criteria.where("name").is("Eugen"));
Update update = new Update();
update.set("name", "Victor");
mongoTemplate.updateMulti(query, update, User.class);

Cả hai đối tượng hiện có sẽ được cập nhật trong cơ sở dữ liệu:

[
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
        "_class" : "com.baeldung.model.User",
        "name" : "Victor"
    },
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
        "_class" : "com.baeldung.model.User",
        "name" : "Victor"
    }
]

5.6. FindAndModify

Thao tác này hoạt động giống như updateMulti , nhưng nó trả về đối tượng trước khi nó được sửa đổi.

Đầu tiên, đây là trạng thái của cơ sở dữ liệu trước khi gọi findAndModify :

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "com.baeldung.model.User",
    "name" : "Markus"
}

Hãy xem mã hoạt động thực tế:

Query query = new Query();
query.addCriteria(Criteria.where("name").is("Markus"));
Update update = new Update();
update.set("name", "Nick");
User user = mongoTemplate.findAndModify(query, update, User.class);

Đối tượng người dùng được trả về có cùng giá trị với trạng thái ban đầu trong cơ sở dữ liệu.

Tuy nhiên, đây là trạng thái mới trong cơ sở dữ liệu:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "com.baeldung.model.User",
    "name" : "Nick"
}

5.7. Nâng cấp

Nâng cao hoạt động trên tìm và sửa đổi ngữ nghĩa tạo khác :nếu tài liệu được khớp, hãy cập nhật nó hoặc nếu không, hãy tạo một tài liệu mới bằng cách kết hợp truy vấn và đối tượng cập nhật.

Hãy bắt đầu với trạng thái ban đầu của cơ sở dữ liệu:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "com.baeldung.model.User",
    "name" : "Markus"
}

Bây giờ, hãy chạy upert :

Query query = new Query();
query.addCriteria(Criteria.where("name").is("Markus"));
Update update = new Update();
update.set("name", "Nick");
mongoTemplate.upsert(query, update, User.class);

Đây là trạng thái của cơ sở dữ liệu sau khi hoạt động:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "com.baeldung.model.User",
    "name" : "Nick"
}

5.8. Xóa

Chúng tôi sẽ xem xét trạng thái của cơ sở dữ liệu trước khi gọi remove :

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "com.baeldung.model.User",
    "name" : "Benn"
}

Bây giờ hãy chạy remove :

mongoTemplate.remove(user, "user");

Kết quả sẽ như mong đợi:

{
}

6. Sử dụng MongoRepository

6.1. Chèn

Đầu tiên, chúng tôi sẽ xem trạng thái của cơ sở dữ liệu trước khi chạy insert :

{
}

Bây giờ chúng tôi sẽ chèn một người dùng mới:

User user = new User();
user.setName("Jon");
userRepository.insert(user);

Và đây là trạng thái cuối của cơ sở dữ liệu:

{
    "_id" : ObjectId("55b4fda5830b550a8c2ca25a"),
    "_class" : "com.baeldung.model.User",
    "name" : "Jon"
}

Lưu ý cách hoạt động giống như thao tác chèn trong MongoTemplate API.

6.2. Lưu - Chèn

Tương tự, lưu hoạt động giống như save hoạt động trong MongoTemplate API.

Hãy bắt đầu bằng cách xem xét ngữ nghĩa chèn của hoạt động.

Đây là trạng thái ban đầu của cơ sở dữ liệu:

{
}

Bây giờ chúng tôi thực hiện lưu hoạt động:

User user = new User();
user.setName("Aaron");
userRepository.save(user);

Điều này dẫn đến việc người dùng được thêm vào cơ sở dữ liệu:

{
    "_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
    "_class" : "com.baeldung.model.User",
    "name" : "Aaron"
}

Lưu ý lại cách lưu hoạt động với insert ngữ nghĩa vì chúng tôi đang chèn một đối tượng mới.

6.3. Lưu - Cập nhật

Bây giờ chúng ta hãy xem xét hoạt động tương tự nhưng với cập nhật ngữ nghĩa.

Đầu tiên, đây là trạng thái của cơ sở dữ liệu trước khi chạy save mới :

{
    "_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
    "_class" : "com.baeldung.model.User",
    "name" : "Jack"81*6
}

Bây giờ chúng ta thực hiện thao tác:

user = mongoTemplate.findOne(
  Query.query(Criteria.where("name").is("Jack")), User.class);
user.setName("Jim");
userRepository.save(user);

Cuối cùng, đây là trạng thái của cơ sở dữ liệu:

{
    "_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
    "_class" : "com.baeldung.model.User",
    "name" : "Jim"
}

Lưu ý lại cách lưu hoạt động với cập nhật ngữ nghĩa vì chúng ta đang sử dụng một đối tượng hiện có.

6.4. Xóa

Đây là trạng thái của cơ sở dữ liệu trước khi gọi xóa :

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "com.baeldung.model.User",
    "name" : "Benn"
}

Hãy chạy xóa :

userRepository.delete(user);

Và đây là kết quả của chúng tôi:

{
}

6.5. FindOne

Tiếp theo, đây là trạng thái của cơ sở dữ liệu khi findOne được gọi là:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "com.baeldung.model.User",
    "name" : "Chris"
}

Bây giờ chúng ta hãy thực thi findOne :

userRepository.findOne(user.getId())

Và kết quả sẽ trả về dữ liệu hiện có:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "com.baeldung.model.User",
    "name" : "Chris"
}

6.6. Tồn tại

Trạng thái của cơ sở dữ liệu trước khi gọi tồn tại :

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "com.baeldung.model.User",
    "name" : "Harris"
}

Bây giờ chúng ta hãy chạy tồn tại , tất nhiên sẽ trả về true :

boolean isExists = userRepository.exists(user.getId());

6.7. FindAll Với Sắp xếp

Trạng thái của cơ sở dữ liệu trước khi gọi findAll :

[
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
        "_class" : "com.baeldung.model.User",
        "name" : "Brendan"
    },
    {
        "_id" : ObjectId("67b5ffa5511fee0e45ed614b"),
        "_class" : "com.baeldung.model.User",
        "name" : "Adam"
    }
]

Bây giờ chúng ta hãy chạy findAll với Sắp xếp :

List<User> users = userRepository.findAll(Sort.by(Sort.Direction.ASC, "name"));

Kết quả sẽ được sắp xếp theo tên theo thứ tự tăng dần :

[
    {
        "_id" : ObjectId("67b5ffa5511fee0e45ed614b"),
        "_class" : "com.baeldung.model.User",
        "name" : "Adam"
    },
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
        "_class" : "com.baeldung.model.User",
        "name" : "Brendan"
    }
]

6.8. FindAll Với Pagable

Trạng thái của cơ sở dữ liệu trước khi gọi findAll :

[
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
        "_class" : "com.baeldung.model.User",
        "name" : "Brendan"
    },
    {
        "_id" : ObjectId("67b5ffa5511fee0e45ed614b"),
        "_class" : "com.baeldung.model.User",
        "name" : "Adam"
    }
]

Bây giờ chúng ta hãy thực thi findAll với yêu cầu phân trang:

Pageable pageableRequest = PageRequest.of(0, 1);
Page<User> page = userRepository.findAll(pageableRequest);
List<User> users = pages.getContent();

Kết quả người dùng danh sách sẽ chỉ có một người dùng:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "com.baeldung.model.User",
    "name" : "Brendan"
}

7. Chú thích

Cuối cùng, chúng ta cũng hãy xem qua các chú thích đơn giản mà Spring Data sử dụng để thúc đẩy các hoạt động API này.

Cấp trường @Id chú thích có thể trang trí bất kỳ loại nào, kể cả long chuỗi :

@Id
private String id;

Nếu giá trị của @Id trường không rỗng, nó được lưu trữ trong cơ sở dữ liệu nguyên trạng; nếu không, bộ chuyển đổi sẽ cho rằng chúng tôi muốn lưu trữ một ObjectId trong cơ sở dữ liệu ( ObjectId , Chuỗi hoặc BigInteger làm việc).

Tiếp theo, chúng ta sẽ xem xét @Document :

@Document
public class User {
    //
}

Chú thích này chỉ đơn giản là đánh dấu một lớp là một đối tượng miền cần được duy trì trong cơ sở dữ liệu, cùng với việc cho phép chúng tôi chọn tên của bộ sưu tập sẽ được sử dụng.


  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Đã nhúng MongoDB khi chạy thử nghiệm tích hợp

  2. Làm cách nào để thay đổi tên bộ sưu tập trong mongoose.model?

  3. Làm cách nào để thiết lập MongoDB trên máy chủ Node.js bằng node-mongodb-native trong môi trường EC2?

  4. Cách lọc mảng trong tài liệu con với MongoDB

  5. Cách mới để quản lý cơ sở dữ liệu nguồn mở