1. Gambaran keseluruhan
Artikel ini akan menjadi pengenalan yang cepat dan praktikal untuk Spring Data MongoDB .
Kami akan membahas asas menggunakan kedua MongoTemplate dan juga MongoRepository menggunakan contoh praktikal untuk menggambarkan setiap operasi.
2. MongoTemplate dan MongoRepository
The MongoTemplate mengikut pola template standard di Spring dan menyediakan bersedia untuk pergi, API asas kepada enjin kegigihan asas.
Repositori ini mengikuti pendekatan Spring Data-centric dan dilengkapi dengan operasi API yang lebih fleksibel dan kompleks, berdasarkan corak akses yang terkenal di semua projek Spring Data.
Untuk kedua-duanya, kita perlu memulakan dengan menentukan kebergantungan - misalnya, dalam pom.xml , dengan Maven:
org.springframework.data spring-data-mongodb 3.0.3.RELEASE
Untuk memeriksa sama ada versi perpustakaan baru telah dikeluarkan - jejak siarannya di sini.
3. Konfigurasi untuk MongoTemplate
3.1. Konfigurasi XML
Mari kita mulakan dengan konfigurasi XML mudah untuk templat Mongo:
Pertama, kita perlu menentukan kacang kilang yang bertanggungjawab untuk membuat contoh Mongo.
Seterusnya - kita perlu menentukan (dan mengkonfigurasi) kacang templat:
Dan akhirnya, kita perlu menentukan pemproses pos untuk menterjemahkan sebarang Pengecualian Mongo yang dilemparkan dalam kelas anotasi @Repository :
3.2. Konfigurasi Java
Mari sekarang buat konfigurasi serupa menggunakan konfigurasi Java dengan memperluas kelas dasar untuk konfigurasi 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"); } }
Catatan: Kami tidak perlu menentukan kacang MongoTemplate dalam konfigurasi sebelumnya kerana ia sudah ditentukan dalam AbstractMongoClientConfiguration.
Kami juga dapat menggunakan konfigurasi kami dari awal tanpa memanjangkan AbstractMongoClientConfiguration - seperti berikut:
@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. Konfigurasi untuk MongoRepository
4.1. Konfigurasi XML
Untuk menggunakan repositori tersuai (memperluas MongoRepository ) - kita perlu meneruskan konfigurasi dari bahagian 3.1 dan menyediakan repositori:
4.2. Konfigurasi Java
Begitu juga, kita akan membina konfigurasi yang telah kita buat di bahagian 3.2 dan menambahkan anotasi baru ke dalam campuran:
@EnableMongoRepositories(basePackages = "com.baeldung.repository")
4.3. Buat Repositori
Sekarang, setelah konfigurasi, kita perlu membuat repositori - memperluas antara muka MongoRepository yang ada :
public interface UserRepository extends MongoRepository { // }
Sekarang kita boleh melakukan auto-wire UserRepository ini dan menggunakan operasi dari MongoRepository atau menambahkan operasi tersuai.
5. Menggunakan MongoTemplate
5.1. Masukkan
Mari mulakan dengan operasi memasukkan; mari kita mulakan juga dengan pangkalan data kosong:
{ }
Sekarang jika kita memasukkan pengguna baru:
User user = new User(); user.setName("Jon"); mongoTemplate.insert(user, "user");
Pangkalan data akan kelihatan seperti ini:
{ "_id" : ObjectId("55b4fda5830b550a8c2ca25a"), "_class" : "com.baeldung.model.User", "name" : "Jon" }
5.2. Simpan - Masukkan
The jimat operasi mempunyai jimat-atau-maklumat semantik: jika id yang hadir, ia melaksanakan kemas kini, jika tidak - ia bersisipan.
Mari lihat semantik pertama - sisipan; berikut adalah keadaan awal pangkalan data :
{ }
Apabila kita sekarang menyimpan pengguna baru:
User user = new User(); user.setName("Albert"); mongoTemplate.save(user, "user");
Entiti akan dimasukkan ke dalam pangkalan data:
{ "_id" : ObjectId("55b52bb7830b8c9b544b6ad5"), "_class" : "com.baeldung.model.User", "name" : "Albert" }
Seterusnya, kita akan melihat operasi yang sama - simpan - dengan semantik kemas kini.
5.3. Simpan - Kemas kini
Sekarang mari kita lihat simpan dengan semantik terkini, beroperasi pada entiti yang ada:
{ "_id" : ObjectId("55b52bb7830b8c9b544b6ad5"), "_class" : "com.baeldung.model.User", "name" : "Jack" }
Sekarang, apabila kita menyimpan pengguna yang ada - kita akan mengemas kini:
user = mongoTemplate.findOne( Query.query(Criteria.where("name").is("Jack")), User.class); user.setName("Jim"); mongoTemplate.save(user, "user");
Pangkalan data akan kelihatan seperti ini:
{ "_id" : ObjectId("55b52bb7830b8c9b544b6ad5"), "_class" : "com.baeldung.model.User", "name" : "Jim" }
As you can see, in this particular example, save uses the semantics of update, because we use an object with given _id.
5.4. UpdateFirst
updateFirst updates the very first document that matches the query.
Let's start with the initial state of the database:
[ { "_id" : ObjectId("55b5ffa5511fee0e45ed614b"), "_class" : "com.baeldung.model.User", "name" : "Alex" }, { "_id" : ObjectId("55b5ffa5511fee0e45ed614c"), "_class" : "com.baeldung.model.User", "name" : "Alex" } ]
When we now run the 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);
Only the first entry will be updated:
[ { "_id" : ObjectId("55b5ffa5511fee0e45ed614b"), "_class" : "com.baeldung.model.User", "name" : "James" }, { "_id" : ObjectId("55b5ffa5511fee0e45ed614c"), "_class" : "com.baeldung.model.User", "name" : "Alex" } ]
5.5. UpdateMulti
UpdateMultiupdates all document that matches the given query.
First – here's the state of the database before doing the updateMulti:
[ { "_id" : ObjectId("55b5ffa5511fee0e45ed614b"), "_class" : "com.baeldung.model.User", "name" : "Eugen" }, { "_id" : ObjectId("55b5ffa5511fee0e45ed614c"), "_class" : "com.baeldung.model.User", "name" : "Eugen" } ]
Now, let's now run the updateMulti operation:
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);
Both existing objects will be updated in the database:
[ { "_id" : ObjectId("55b5ffa5511fee0e45ed614b"), "_class" : "com.baeldung.model.User", "name" : "Victor" }, { "_id" : ObjectId("55b5ffa5511fee0e45ed614c"), "_class" : "com.baeldung.model.User", "name" : "Victor" } ]
5.6. FindAndModify
This operation works like updateMulti, but it returns the object before it was modified.
First – the state of the database before calling findAndModify:
{ "_id" : ObjectId("55b5ffa5511fee0e45ed614b"), "_class" : "com.baeldung.model.User", "name" : "Markus" }
Let's look at the actual operation code:
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);
The returned user object has the same values as the initial state in the database.
However, the new state in the database is:
{ "_id" : ObjectId("55b5ffa5511fee0e45ed614b"), "_class" : "com.baeldung.model.User", "name" : "Nick" }
5.7. Upsert
The upsert works operate on the find and modify else create semantics: if the document is matched, update it, else create a new document by combining the query and update object.
Let's start with the initial state of the database:
{ "_id" : ObjectId("55b5ffa5511fee0e45ed614b"), "_class" : "com.baeldung.model.User", "name" : "Markus" }
Now – let's run the upsert:
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);
Here's the state of the database after the operation:
{ "_id" : ObjectId("55b5ffa5511fee0e45ed614b"), "_class" : "com.baeldung.model.User", "name" : "Nick" }
5.8. Remove
The state of the database before calling remove:
{ "_id" : ObjectId("55b5ffa5511fee0e45ed614b"), "_class" : "com.baeldung.model.User", "name" : "Benn" }
Let's now run remove:
mongoTemplate.remove(user, "user");
The result will be as expected:
{ }
6. Using MongoRepository
6.1. Insert
First – the state of the database before running the insert:
{ }
Now, when we insert a new user:
User user = new User(); user.setName("Jon"); userRepository.insert(user);
Here's the end state of the database:
{ "_id" : ObjectId("55b4fda5830b550a8c2ca25a"), "_class" : "com.baeldung.model.User", "name" : "Jon" }
Note how the operation works the same as the insert in the MongoTemplate API.
6.2. Save – Insert
Similarly – save works the same as the save operation in the MongoTemplate API.
Let's start by looking at the insert semantics of the operation; here's the initial state of the database:
{ }
Now – we execute the save operation:
User user = new User(); user.setName("Aaron"); userRepository.save(user);
This results in the user being added to the database:
{ "_id" : ObjectId("55b52bb7830b8c9b544b6ad5"), "_class" : "com.baeldung.model.User", "name" : "Aaron" }
Note again how, in this example, save works with insert semantics, because we are inserting a new object.
6.3. Save – Update
Let's now look at the same operation but with update semantics.
First – here's the state of the database before running the new save:
{ "_id" : ObjectId("55b52bb7830b8c9b544b6ad5"), "_class" : "com.baeldung.model.User", "name" : "Jack"81*6 }
Now – we execute the operation:
user = mongoTemplate.findOne( Query.query(Criteria.where("name").is("Jack")), User.class); user.setName("Jim"); userRepository.save(user);
Finally, here is the state of the database:
{ "_id" : ObjectId("55b52bb7830b8c9b544b6ad5"), "_class" : "com.baeldung.model.User", "name" : "Jim" }
Note again how, in this example, save works with update semantics, because we are using an existing object.
6.4. Delete
The state of the database before calling delete:
{ "_id" : ObjectId("55b5ffa5511fee0e45ed614b"), "_class" : "com.baeldung.model.User", "name" : "Benn" }
Let's run delete:
userRepository.delete(user);
The result will simply be:
{ }
6.5. FindOne
The state of the database when findOne is called:
{ "_id" : ObjectId("55b5ffa5511fee0e45ed614b"), "_class" : "com.baeldung.model.User", "name" : "Chris" }
Let's now execute the findOne:
userRepository.findOne(user.getId())
The result which will return the existing data:
{ "_id" : ObjectId("55b5ffa5511fee0e45ed614b"), "_class" : "com.baeldung.model.User", "name" : "Chris" }
6.6. Exists
The state of the database before calling exists:
{ "_id" : ObjectId("55b5ffa5511fee0e45ed614b"), "_class" : "com.baeldung.model.User", "name" : "Harris" }
Now, let's run exists:
boolean isExists = userRepository.exists(user.getId());
Which of course will return true.
6.7. FindAll W ith Sort
The state of the database before calling findAll:
[ { "_id" : ObjectId("55b5ffa5511fee0e45ed614b"), "_class" : "com.baeldung.model.User", "name" : "Brendan" }, { "_id" : ObjectId("67b5ffa5511fee0e45ed614b"), "_class" : "com.baeldung.model.User", "name" : "Adam" } ]
Let's now run findAll with Sort:
List users = userRepository.findAll(Sort.by(Sort.Direction.ASC, "name"));
The result will be sorted by name in ascending order:
[ { "_id" : ObjectId("67b5ffa5511fee0e45ed614b"), "_class" : "com.baeldung.model.User", "name" : "Adam" }, { "_id" : ObjectId("55b5ffa5511fee0e45ed614b"), "_class" : "com.baeldung.model.User", "name" : "Brendan" } ]
6.8. FindAll W ith Pageable
The state of the database before calling findAll:
[ { "_id" : ObjectId("55b5ffa5511fee0e45ed614b"), "_class" : "com.baeldung.model.User", "name" : "Brendan" }, { "_id" : ObjectId("67b5ffa5511fee0e45ed614b"), "_class" : "com.baeldung.model.User", "name" : "Adam" } ]
Let's now execute findAll with a pagination request:
Pageable pageableRequest = PageRequest.of(0, 1); Page page = userRepository.findAll(pageableRequest); List users = pages.getContent();
The resulting users list will be only one user:
{ "_id" : ObjectId("55b5ffa5511fee0e45ed614b"), "_class" : "com.baeldung.model.User", "name" : "Brendan" }
7. Annotations
Finally, let's also go over the simple annotations that Spring Data uses to drive these API operations.
@Id private String id;
The field level @Id annotation can decorate any type, including long and string.
If the value of the @Id field is not null, it's stored in the database as-is; otherwise, the converter will assume you want to store an ObjectId in the database (either ObjectId, String or BigInteger work).
Next – @Document:
@Document public class User { // }
This annotation simply marks a class as being a domain object that needs to be persisted to the database, along with allowing us to choose the name of the collection to be used.
8. Conclusion
This article was a quick but comprehensive introduction to using MongoDB with Spring Data, both via the MongoTemplate API as well as making use of MongoRepository.
The implementation of all these examples and code snippets can be found over on Github.