Original title: Spring Data MongoDB reference document II (content source: Spring China Education Management Center)
11.3.3.MongoDatabaseFactory interface
although
com.mongodb.client.MongoClient is the entry point of MongoDB driver API, but connecting to a specific MongoDB database instance requires other information, such as database name and optional user name and password. Using this information, you can get a com.mongodb.client.MongoDatabase object and access all functions of a specific MongoDB database instance. Spring provides org. S Pringframework.data.MongoDB.core.mongodatabasefactory uses the interface shown in the following list to guide the connection to the database:
public interface MongoDatabaseFactory { MongoDatabase getDatabase() throws DataAccessException; MongoDatabase getDatabase(String dbName) throws DataAccessException; }
The following section shows how to use a container with Java based or XML based metadata to configure an instance of the MongoDatabaseFactory interface. Conversely, you can use the MongoDatabaseFactory instance to configure the MongoTemplate
You can use them in standard Java code instead of using IoC container to create an instance of MongoTemplate, as follows:
public class MongoApp { private static final Log log = LogFactory.getLog(MongoApp.class); public static void main(String[] args) throws Exception { MongoOperations mongoOps = new MongoTemplate(new SimpleMongoClientDatabaseFactory(MongoClients.create(), "database")); mongoOps.insert(new Person("Joe", 34)); log.info(mongoOps.findOne(new Query(where("name").is("Joe")), Person.class)); mongoOps.dropCollection("person"); } }
Bold code highlights
The only difference between SimpleMongoClientDbFactory and the listing shown in the getting started section.
SimpleMongoClientDbFactory is used when selecting com.mongodb.client.MongoClient as the selected entry point.
11.3.4.MongoDatabaseFactory uses Java based metadata to register instances
To register an instance with the MongoDatabaseFactory container, the code you write is very similar to that highlighted in the previous code listing. The following listing shows a simple example:
@Configuration public class MongoConfiguration { public @Bean MongoDatabaseFactory mongoDatabaseFactory() { return new SimpleMongoClientDatabaseFactory(MongoClients.create(), "database"); } }
The 3rd generation of MongoDB server changed the authentication model when connecting to the database. Therefore, some configuration options available for authentication are no longer valid. You should use the mongoclient specific option to set the credential MongoCredential to provide authentication data, as shown in the following example:
@Configuration public class ApplicationContextEventTestsAppConfig extends AbstractMongoClientConfiguration { @Override public String getDatabaseName() { return "database"; } @Override protected void configureClientSettings(Builder builder) { builder .credential(MongoCredential.createCredential("name", "db", "pwd".toCharArray())) .applyToClusterSettings(settings -> { settings.hosts(singletonList(new ServerAddress("127.0.0.1", 27017))); }); } }
To use authentication in an XML based configuration, use the attribute < Mongo client > on the element credential.
The username and password credentials used in an XML based configuration must contain reserved characters when URL encoding is used, such as:%, @, or. The following example shows the encoded credentials: m0ng0@dmin:mo_res:bw6},Qsdxx@admin@database→
m0ng0%40dmin:mo_res%3Abw6%7D%2CQsdxx%40admin@database For more details, please refer to Section 2.2 of RFC 3986.
11.3.5.MongoDatabaseFactory uses XML based metadata to register instances
The mongo namespace provides a convenient way to create a
SimpleMongoClientDbFactory, because compared with using < beans / > namespace, as shown in the following example:
<mongo:db-factory dbname="database">
If you need to
com.mongodb.client.MongoClient is used to configure other options SimpleMongoClientDbFactory on the created instance. You can use Mongo ref to reference existing bean s with the properties shown in the following example. To show another common usage pattern, the following listing shows the use of property placeholders, which allows you to parameterize the configuration and creation of mongotemplates:
<context:property-placeholder location="classpath:/com/myapp/mongodb/config/mongo.properties"/> <mongo:mongo-client host="${mongo.host}" port="${mongo.port}"> <mongo:client-settings connection-pool-max-connection-life-time="${mongo.pool-max-life-time}" connection-pool-min-size="${mongo.pool-min-size}" connection-pool-max-size="${mongo.pool-max-size}" connection-pool-maintenance-frequency="10" connection-pool-maintenance-initial-delay="11" connection-pool-max-connection-idle-time="30" connection-pool-max-wait-time="15" /> </mongo:mongo-client> <mongo:db-factory dbname="database" mongo-ref="mongoClient"/> <bean id="anotherMongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate"> <constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/> </bean>
11.4. Introduction MongoTemplate
The MongoTemplate class is located in
org.springframework.data.mongodb.core package is the support of MongoDB of Spring at the central level, and provides a rich set of functions for interacting with the database. The template provides convenient operations for creating, updating, deleting and querying MongoDB documents, and provides mapping between domain objects and MongoDB documents.
After configuration, MongoTemplate is thread safe and can be reused in multiple instances.
The mapping between MongoDB documents and domain classes is done by delegating the implementation of the MongoConverter interface. Spring provides MappingMongoConverter, but you can also write your own converter. For more details, see "custom conversion - overwrite default mapping".
This MongoTemplate class implements the interface MongoOperations. As far as possible, MongoOperations is named after the methods available on the MongoDB driver Collection object, so that existing MongoDB developers using the driver API are familiar with the API. For example, you can find methods, such as find, findAndModify, findAndReplace, findOne, insert, remove, save, update , and updateMulti. The design goal is to easily between the basic MongoDB driver and MongoOperations. The main difference between the two APIs is that MongoOperations can pass domain objects instead of documents. In addition, MongoOperations has fluent API Query, Criteria and update operations instead of filling in a Document to specify the parameters of these operations.
The preferred way to reference MongoTemplate instance operations is through its interface MongoOperations
The default converter used to implement MongoTemplate is MappingMongoConverter. Although MappingMongoConverter can use additional metadata to specify the mapping of objects to documents, it can also use some conventions of mapping ID and collection name to convert objects that do not contain additional data. These conventions and the use of mapping annotations are in mapping It is explained in the chapter.
Another core function of MongoTemplate is to convert the exceptions thrown by MongoDB Java driver into Spring's portable data access exception hierarchy. For more information, see "exception translation".
MongoTemplate provides many convenient methods to help you easily perform common tasks. However, if you need direct access to the MongoDB driver API, you can use one of several execute callback methods. The execute callback gives you any reference
com.mongodb.client.MongoCollection or com.mongodb.client.MongoDatabase object. For more information, see the "execute callback" section.
The next section contains an example of how MongoTemplate can be used in the context of the Spring container.
11.4.1. Instantiate MongoTemplate
You can use Java to create and register an instance of MongoTemplate, as shown in the following example:
Example 61. Register a
com.mongodb.client.MongoClient object and enable Spring's exception conversion support
@Configuration public class AppConfig { public @Bean MongoClient mongoClient() { return MongoClients.create("mongodb://localhost:27017"); } public @Bean MongoTemplate mongoTemplate() { return new MongoTemplate(mongoClient(), "mydatabase"); } }
There are several overloaded constructors, MongoTemplate:
- Mongotemplate (MongoClient, Mongo, string databasename): operate with MongoClient object and default database name.
- MongoTemplate(MongoDatabaseFactory mongoDbFactory): a MongoDbFactory object that encapsulates the MongoClient object, database name, user name and password.
- Mongotemplate (mongodatabasefactory, mongodbfactory, MongoConverter, MongoConverter): add a MongoConverter for mapping.
You can also configure MongoTemplate using Spring's XML < beans / > schema, as shown in the following example:
<mongo:mongo-client host="localhost" port="27017"/> <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate"> <constructor-arg ref="mongoClient"/> <constructor-arg name="databaseName" value="geospatial"/> </bean>
You may want to set optional properties during other creation. MongoTemplate is the default WriteResultCheckingPolicy, WriteConcern and ReadPreference properties.
The preferred way to reference MongoTemplate instance operations is through its interface MongoOperations
11.4.2.WriteResultChecking policy
In development, it is convenient to record or throw exceptions if com.mongodb.WriteResult contains errors returned from any MongoDB operation. It's common to forget to do this during development, and then end up with an application that looks successful, when in fact, the database has not been modified as you expected. You can set the WriteResultChecking property of MongoTemplate to one of the following values: exception or NONE, which are used to throw an exception or do nothing, respectively. The default value is the WriteResultChecking value NONE used.
11.4.3.WriteConcern
If not already specified by a higher-level driver (for example
com.mongodb.client.MongoClient), you can set the com.mongodb.WriteConcern property MongoTemplate for write operations. If WriteConcern does not set this property, it defaults to the setting in the DB or Collection settings of the MongoDB driver.
11.4.4.WriteConcernResolver
For more advanced cases, you want WriteConcern to set different values (for delete, update, insert and save operations) based on each operation. WriteConcern resolver can be in MongoTemplate. Because MongoTemplate is used to persist POJOs, WriteConcern resolver can create a policy to map specific POJO classes to a WriteConcern value. The following listing shows the WriteConcernResolver interface:
public interface WriteConcernResolver { WriteConcern resolve(MongoAction action); }
You can use the MongoAction parameter to determine the WriteConcern value or use the value of the template itself as the default value. MongoAction includes POJO described in java.lang.Class, converted Document, operation (REMOVE, UPDATE, INSERT, INSERT_LIST, or SAVE), and other contextual information when the collection name is written. The following example shows two sets of classes that get different writeconcert settings:
private class MyAppWriteConcernResolver implements WriteConcernResolver { public WriteConcern resolve(MongoAction action) { if (action.getEntityClass().getSimpleName().contains("Audit")) { return WriteConcern.NONE; } else if (action.getEntityClass().getSimpleName().contains("Metadata")) { return WriteConcern.JOURNAL_SAFE; } return action.getDefaultWriteConcern(); } }
11.5. Saving, updating and deleting documents
MongoTemplate allows you to save, update, and delete domain objects and map them to documents stored in MongoDB.
Consider the following categories:
public class Person { private String id; private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } public String getId() { return id; } public String getName() { return name; } public int getAge() { return age; } @Override public String toString() { return "Person [id=" + id + ", name=" + name + ", age=" + age + "]"; } }
Given the class in the previous example of Person, you can save, update, and delete objects, as shown in the following example:
MongoOperations is the interface implemented by MongoTemplate.
package org.spring.example; import static org.springframework.data.mongodb.core.query.Criteria.where; import static org.springframework.data.mongodb.core.query.Update.update; import static org.springframework.data.mongodb.core.query.Query.query; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.SimpleMongoClientDbFactory; import com.mongodb.client.MongoClients; public class MongoApp { private static final Log log = LogFactory.getLog(MongoApp.class); public static void main(String[] args) { MongoOperations mongoOps = new MongoTemplate(new SimpleMongoClientDbFactory(MongoClients.create(), "database")); Person p = new Person("Joe", 34); // Insert is used to initially store the object into the database. mongoOps.insert(p); log.info("Insert: " + p); // Find p = mongoOps.findById(p.getId(), Person.class); log.info("Found: " + p); // Update mongoOps.updateFirst(query(where("name").is("Joe")), update("age", 35), Person.class); p = mongoOps.findOne(query(where("name").is("Joe")), Person.class); log.info("Updated: " + p); // Delete mongoOps.remove(p); // Check that deletion worked List<Person> people = mongoOps.findAll(Person.class); log.info("Number of people = : " + people.size()); mongoOps.dropCollection(Person.class); } }
The previous example will produce the following log output (including the debug message MongoTemplate from):
DEBUG apping.MongoPersistentEntityIndexCreator: 80 - Analyzing class class org.spring.example.Person for index information. DEBUG work.data.mongodb.core.MongoTemplate: 632 - insert Document containing fields: [_class, age, name] in collection: person INFO org.spring.example.MongoApp: 30 - Insert: Person [id=4ddc6e784ce5b1eba3ceaf5c, name=Joe, age=34] DEBUG work.data.mongodb.core.MongoTemplate:1246 - findOne using query: { "_id" : { "$oid" : "4ddc6e784ce5b1eba3ceaf5c"}} in db.collection: database.person INFO org.spring.example.MongoApp: 34 - Found: Person [id=4ddc6e784ce5b1eba3ceaf5c, name=Joe, age=34] DEBUG work.data.mongodb.core.MongoTemplate: 778 - calling update using query: { "name" : "Joe"} and update: { "$set" : { "age" : 35}} in collection: person DEBUG work.data.mongodb.core.MongoTemplate:1246 - findOne using query: { "name" : "Joe"} in db.collection: database.person INFO org.spring.example.MongoApp: 39 - Updated: Person [id=4ddc6e784ce5b1eba3ceaf5c, name=Joe, age=35] DEBUG work.data.mongodb.core.MongoTemplate: 823 - remove using query: { "id" : "4ddc6e784ce5b1eba3ceaf5c"} in collection: person INFO org.spring.example.MongoApp: 46 - Number of people = : 0 DEBUG work.data.mongodb.core.MongoTemplate: 376 - Dropped collection [database.person]
MongoConverter implicitly converts ObjectId between a and an stored in the database by identifying (by convention) the attribute name String.
The previous examples are intended to demonstrate the use of save, update, and delete operations, rather than the complex mapping capabilities of the MongoTemplate.
The query syntax used in the previous example is explained in more detail in the "query document" section.
11.5.1. How to_ id processes fields in the mapping layer
MongoDB requires you to have one_ id contains fields for all documents. If you do not provide, the driver assigns ObjectId a generated value. When you use MappingMongoConverter, some rules control how properties in Java classes are mapped to this_ id field:
- Attributes or fields annotated with @ id (org. Springframework. Data. Annotation. id) are mapped to the_ id field.
- A named attribute or field id without comments is mapped to the_ id field.
The following is an overview_ id type conversion (if any) of attributes mapped to document fields when using MappingMongoConverter (MongoTemplate by default).
- If possible, the attribute or field whose id is declared as a in the Java class is converted to and stored as an by using spring string. Valid conversion rules are delegated to the MongoDB Java driver. If it cannot be converted to, the value is stored in the database as a string. ObjectIdConverter<String, ObjectId>ObjectId
- Use Spring to convert and store the attribute or field BigInteger declared in the Java class id as. ObjectIdConverter<BigInteger, ObjectId>
If the field or property specified in the previous rule set does not exist in the Java class_ id, the driver generates an implicit file, but does not map to the properties or fields of the Java class.
When querying and updating, MongoTemplate uses the converter corresponding to the above rules to save the document, so that the field name and type used in the query can match the content in the domain class.
Some environments require custom methods to map id values, such as data stored in MongoDB that does not run through the Spring Data mapping layer. Documents can contain_ id can be expressed as ObjectId or String. The read document back to domain type from storage is working properly. id due to implicit ObjectId transformations, querying documents through them can be cumbersome. Therefore, the document cannot be retrieved in this way. For these cases, @ MongoId provides more control over actual id mapping attempts.
Example 62.@MongoId mapping
public class PlainStringId { @MongoId String id; } public class PlainObjectId { @MongoId ObjectId id; } public class StringToObjectId { @MongoId(FieldType.OBJECT_ID) String id; }
11.5.2. Type mapping
The MongoDB collection can contain documents representing various types of instances. This is useful if you store a hierarchy of classes or a class with a type attribute. In the latter case, the value saved in the property must be read correctly when retrieving the Object. Therefore, we need a mechanism to store type information with the actual document.
To achieve this, its MappingMongoConverter uses a MongoTypeMapper abstraction DefaultMongoTypeMapper as its main implementation. Its default behavior is_ Class stores the fully qualified class name inside the document. Write type hints and subtypes of declared attribute types for the top-level document and each value if it is a complex type. The following example (with JSON representation at the end) shows how mapping works:
Example 63. Type mapping
public class Sample { Contact value; } public abstract class Contact { ... } public class Person extends Contact { ... } Sample sample = new Sample(); sample.value = new Person(); mongoTemplate.save(sample); { "value" : { "_class" : "com.acme.Person" }, "_class" : "com.acme.Sample" }
Spring Data MongoDB stores type information as the actual root class and the last field of the nested type (because it is complex and is a subtype of Contact). Therefore, if you now use mongoTemplate.findAll(Object.class, "sample"), you can find that the stored document is a Sample instance. You can also find that the value attribute is actually a Person
Content source: Spring China Education Management Center (spring certification)
In February 2021, VMware officially reached a strategic cooperation with Beijing Zhongke Zhuowang Network Technology Co., Ltd. (hereinafter referred to as Zhongke Zhuowang), and awarded its Spring China Education Management Center to join hands with VMware's latest Spring technology and certification system to help Chinese colleges and universities build professional teaching content and fully empower future developers.