原標題:Spring認證中國教育管理中心-Spring Data MongoDB教程十三(內容來源:Spring中國教育管理中心) 18.1.4.Kotlin 支持Spring Data 調整了 Kotlin 的細節(jié)以允許創(chuàng)建和更改對象。 Kotlin 對象創(chuàng)建Kotlin 類支持實例化,默認情況下所有類都是不可變的,并且需要顯式屬性聲明來定義可變屬性??紤]以下data類Person: data class Person(val id: String, val name: String) 上面的類編譯為具有顯式構造函數的典型類。我們可以通過添加另一個構造函數來自定義這個類,并使用注釋@PersistenceConstructor來指示構造函數首選項: data class Person(var id: String, val name: String) { @PersistenceConstructor constructor(id: String) : this(id, "unknown") } Kotlin 通過允許在未提供參數時使用默認值來支持參數可選性。當 Spring Data 檢測到具有參數默認值的構造函數時,如果數據存儲不提供值(或簡單地返回null),它就會使這些參數不存在,因此 Kotlin 可以應用參數默認值??紤]以下應用參數默認值的類name data class Person(var id: String, val name: String = "unknown") 每次name參數不是結果的一部分或其值為 時null,則name默認為unknown。 Kotlin 數據類的屬性填充在 Kotlin 中,默認情況下所有類都是不可變的,并且需要明確的屬性聲明來定義可變屬性。考慮以下data類Person: data class Person(val id: String, val name: String) 這個類實際上是不可變的。它允許創(chuàng)建新實例,因為 Kotlin 生成copy(…)創(chuàng)建新對象實例的方法,該方法從現(xiàn)有對象復制所有屬性值并將作為參數提供的屬性值應用到該方法。 Kotlin 覆蓋屬性Kotlin 允許聲明屬性覆蓋來改變子類中的屬性。 open class SuperType(open var field: Int)class SubType(override var field: Int = 1) : SuperType(field) { } 這樣的安排呈現(xiàn)了兩個名稱為 的屬性field。Kotlin 為每個類中的每個屬性生成屬性訪問器(getter 和 setter)。實際上,代碼如下所示: public class SuperType { private int field; public SuperType(int field) { this.field = field; } public int getField() { return this.field; } public void setField(int field) { this.field = field; } }public final class SubType extends SuperType { private int field; public SubType(int field) { super(field); this.field = field; } public int getField() { return this.field; } public void setField(int field) { this.field = field; } } getter 和 setterSubType只在set 上,SubType.field而不是SuperType.field. 在這種安排中,使用構造函數是設置的唯一默認方法SuperType.field。添加方法 to SubTypeset Spring Data 模塊通常支持包含不同值的覆蓋屬性。從編程模型的角度來看,需要考慮以下幾點:
18.2.基于約定的映射MappingMongoConverter當沒有提供額外的映射元數據時,有一些將對象映射到文檔的約定。這些約定是:
18.2.1._id在映射層中如何處理字段。MongoDB 要求您有一個_id包含所有文檔的字段。如果您不提供,驅動程序將分配一個帶有生成值的 ObjectId。“_id”字段可以是除數組以外的任何類型,只要它是唯一的。驅動程序自然支持所有原始類型和日期。使用 時,MappingMongoConverter有一些規(guī)則控制 Java 類中的屬性如何映射到此_id字段。 以下概述了將映射到_id文檔字段的字段:
下面概述了對映射到 _id 文檔字段的屬性進行的類型轉換(如果有)。
查詢和更新時MongoTemplate將使用轉換器來處理與上述保存文檔規(guī)則相對應的Query和Update對象的轉換,因此查詢中使用的字段名稱和類型將能夠匹配域類中的內容。 18.3.數據映射和類型轉換本節(jié)解釋了類型如何映射到 MongoDB 表示和從 MongoDB 表示映射。Spring Data MongoDB 支持所有可以表示為 BSON(MongoDB 的內部文檔格式)的類型。除了這些類型之外,Spring Data MongoDB 還提供了一組內置轉換器來映射其他類型。您可以提供自己的轉換器來調整類型轉換。有關更多詳細信息,請參閱[ 下面提供了每種可用類型轉換的示例: 18.4.映射配置除非明確配置,否則MappingMongoConverter在創(chuàng)建MongoTemplate. 您可以創(chuàng)建自己的MappingMongoConverter. 這樣做可以讓您指定在類路徑中可以找到域類的位置,以便 Spring Data MongoDB 可以提取元數據并構建索引。此外,通過創(chuàng)建您自己的實例,您可以注冊 Spring 轉換器以將特定類映射到數據庫或從數據庫映射。 您可以使用基于 Java 或基于 XML 的元數據來配置MappingMongoConverter以及 Example 180.@Configuration 類來配置 MongoDB 映射支持 @Configurationpublic class MongoConfig extends AbstractMongoClientConfiguration { @Override public String getDatabaseName() { return "database"; } // the following are optional @Override public String getMappingBasePackage() { return "com.bigbank.domain"; } @Override void configureConverters(MongoConverterConfigurationAdapter adapter) { adapter.registerConverter(new org.springframework.data.mongodb.test.PersonReadConverter()); adapter.registerConverter(new org.springframework.data.mongodb.test.PersonWriteConverter()); } @Bean public LoggingEventListener<MongoMappingEvent> mappingEventsListener() { return new LoggingEventListener<MongoMappingEvent>(); } } 映射基礎包定義了用于掃描用于預初始化MappingContext. 默認情況下使用配置類包。 為特定域類型配置額外的自定義轉換器,用您的自定義實現(xiàn)替換這些類型的默認映射過程。
您可以通過覆蓋該
Spring 的 MongoDB 命名空間允許您在 XML 中啟用映射功能,如以下示例所示: 示例 181.配置 MongoDB 映射支持的 XML 模式 <?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www./schema/beans" xmlns:xsi="http://www./2001/XMLSchema-instance" xmlns:mongo="http://www./schema/data/mongo" xsi:schemaLocation=" http://www./schema/data/mongo https://www./schema/data/mongo/spring-mongo.xsd http://www./schema/beans https://www./schema/beans/spring-beans-3.0.xsd"> <!-- Default bean name is 'mongo' --> <mongo:mongo-client host="localhost" port="27017"/> <mongo:db-factory dbname="database" mongo-ref="mongoClient"/> <!-- by default look for a Mongo object named 'mongo' - default name used for the converter is 'mappingConverter' --> <mongo:mapping-converter base-package="com.bigbank.domain"> <mongo:custom-converters> <mongo:converter ref="readConverter"/> <mongo:converter> <bean class="org.springframework.data.mongodb.test.PersonWriteConverter"/> </mongo:converter> </mongo:custom-converters> </mongo:mapping-converter> <bean id="readConverter" class="org.springframework.data.mongodb.test.PersonReadConverter"/> <!-- set the mapping converter to be used by the MongoTemplate --> <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate"> <constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/> <constructor-arg name="mongoConverter" ref="mappingConverter"/> </bean> <bean class="org.springframework.data.mongodb.core.mapping.event.LoggingEventListener"/></beans> 該base-package屬性告訴它在哪里掃描用@ 18.5.基于元數據的映射要充分利用 Spring Data MongoDB 支持中的對象映射功能,您應該使用注釋對映射對象進行@Document注釋。盡管映射框架沒有必要具有此注釋(您的 POJO 已正確映射,即使沒有任何注釋),但它允許類路徑掃描器查找和預處理您的域對象以提取必要的元數據。如果你不使用這個注解,你的應用程序在你第一次存儲域對象時會受到輕微的性能影響,因為映射框架需要建立它的內部元數據模型,以便它知道你的域對象的屬性以及如何堅持他們。以下示例顯示了一個域對象: 示例 182. 示例域對象 package com.mycompany.domain;@Documentpublic class Person { @Id private ObjectId id; @Indexed private Integer ssn; private String firstName; @Indexed private String lastName; } 該@Id注解告訴你要使用MongoDB的哪個屬性映射器_id屬性和@Indexed注解告訴映射框架調用createIndex(…)你的文檔的那個屬性,使得搜索速度更快。自動索引創(chuàng)建僅適用于用@Document. 默認情況下禁用 自動索引創(chuàng)建,需要通過配置啟用(請參閱索引創(chuàng)建)。 18.5.1.索引創(chuàng)建Spring Data MongoDB 可以自動為使用@Document. 自 3.0 版起,必須顯式啟用索引創(chuàng)建,以防止對集合生命周期和性能影響產生不良影響。在應用程序啟動時以及在應用程序運行時第一次訪問實體類型時,會為初始實體集自動創(chuàng)建索引。 我們通常建議為基于應用程序的索引控制顯式創(chuàng)建索引,因為 Spring Data 無法為在應用程序運行時重新創(chuàng)建的集合自動創(chuàng)建索引。 IndexResolver如果您想使用@Indexed諸如@GeoSpatialIndexed, @TextIndexed,之類的注釋,則為程序化索引定義創(chuàng)建提供抽象@CompoundIndex。您可以使用索引定義IndexOperations來創(chuàng)建索引。創(chuàng)建索引的一個好時機是在應用程序啟動時,特別是在應用程序上下文刷新之后,由觀察觸發(fā)ContextRefreshedEvent。此事件保證上下文已完全初始化。請注意,此時其他組件,尤其是 bean 工廠可能可以訪問 MongoDB 數據庫。 示例 183. 單一域類型的程序化索引創(chuàng)建 class MyListener { @EventListener(ContextRefreshedEvent.class) public void initIndicesAfterStartup() { MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext = mongoTemplate .getConverter().getMappingContext(); IndexResolver resolver = new MongoPersistentEntityIndexResolver(mappingContext); IndexOperations indexOps = mongoTemplate.indexOps(DomainType.class); resolver.resolveIndexFor(DomainType.class).forEach(indexOps::ensureIndex); } } 示例 184. 為所有初始實體創(chuàng)建程序索引 class MyListener{ @EventListener(ContextRefreshedEvent.class) public void initIndicesAfterStartup() { MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext = mongoTemplate .getConverter().getMappingContext(); // consider only entities that are annotated with @Document mappingContext.getPersistentEntities() .stream() .filter(it -> it.isAnnotationPresent(Document.class)) .forEach(it -> { IndexOperations indexOps = mongoTemplate.indexOps(it.getType()); resolver.resolveIndexFor(it.getType()).forEach(indexOps::ensureIndex); }); } } 或者,如果您想在任何組件能夠從您的應用程序訪問您的數據庫之前確保索引和集合存在,請在返回對象之前聲明一個@Bean方法MongoTemplate并包含上面的代碼MongoTemplate。 要關閉自動創(chuàng)建索引ON請覆蓋autoIndexCreation()在你的配置。 @Configuration public class Config extends AbstractMongoClientConfiguration { @Override public boolean autoIndexCreation() { return true; } // ... } 自3.0 版起,自動索引創(chuàng)建默認關閉。 18.5.2.映射注釋概述MappingMongoConverter 可以使用元數據來驅動對象到文檔的映射。以下注釋可用:
映射元數據基礎設施在一個獨立的 spring-data-commons 項目中定義,該項目與技術無關。MongoDB 支持中使用特定子類來支持基于注釋的元數據。如果有需求,也可以采取其他策略。 這是一個更復雜的映射示例。 @Document@CompoundIndex(name = "age_idx", def = "{'lastName': 1, 'age': -1}")public class Person<T extends Address> { @Id private String id; @Indexed(unique = true) private Integer ssn; @Field("fName") private String firstName; @Indexed private String lastName; private Integer age; @Transient private Integer accountTotal; @DBRef private List<Account> accounts; private T address; public Person(Integer ssn) { this.ssn = ssn; } @PersistenceConstructor public Person(Integer ssn, String firstName, String lastName, Integer age, T address) { this.ssn = ssn; this.firstName = firstName; this.lastName = lastName; this.age = age; this.address = address; } public String getId() { return id; } // no setter for Id. (getter is only exposed for some unit testing) public Integer getSsn() { return ssn; }// other getters/setters omitted} @Field(targetType=…)當映射基礎設施推斷的本機 MongoDB 類型與預期的類型不匹配時,可以派上用場。就像 for BigDecimal,它被表示為String而不是Decimal128,只是因為早期版本的 MongoDB Server 不支持它。 public class Balance { @Field(targetType = DECIMAL128) private BigDecimal value; // ... } 您甚至可以考慮自己的自定義注釋。 @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Field(targetType = FieldType.DECIMAL128) public @interface Decimal128 { } // ... public class Balance { @Decimal128 private BigDecimal value; // ... } 18.5.3.自定義對象構建映射子系統(tǒng)允許通過使用注釋對構造函數進行注釋來定制對象構造@PersistenceConstructor。用于構造函數參數的值按以下方式解析:
class OrderItem { private @Id String id; private int quantity; private double unitPrice; OrderItem(String id, @Value("#root.qty ?: 0") int quantity, double unitPrice) { this.id = id; this.quantity = quantity; this.unitPrice = unitPrice; } // getters/setters ommitted} Document input = new Document("id", "4711"); input.put("unitPrice", 2.5); input.put("qty",5); OrderItem item = converter.read(OrderItem.class, input); 如果無法解析給定的屬性路徑@Value,則quantity參數注釋中的 SpEL 表達式將回退到該值0。 @PersistenceConstructor可以在 18.5.4. 復合索引 還支持復合索引。它們是在類級別而不是在單個屬性上定義的。 復合索引對于提高涉及多個字段條件的查詢的性能非常重要 這是一個lastName以升序和age降序創(chuàng)建復合索引的示例: 示例 185. 示例復合索引用法 package com.mycompany.domain;@Document@CompoundIndex(name = "age_idx", def = "{'lastName': 1, 'age': -1}")public class Person { @Id private ObjectId id; private Integer age; private String firstName; private String lastName; } @CompoundIndex可重復使用@CompoundIndexes作為其容器。 @Document@CompoundIndex(name = "cmp-idx-one", def = "{'firstname': 1, 'lastname': -1}")@CompoundIndex(name = "cmp-idx-two", def = "{'address.city': -1, 'address.street': 1}") public class Person { String firstname; String lastname; Address address; // ...} 18.5.5.哈希索引散列索引允許在分片集群中進行基于散列的分片。使用散列字段值對集合進行分片會導致更隨機的分布。有關詳細信息,請參閱MongoDB 文檔。 下面是一個創(chuàng)建哈希索引的示例_id: 示例 186. 哈希索引使用示例 @Documentpublic class DomainType { @HashIndexed @Id String id; // ...} 可以在其他索引定義旁邊創(chuàng)建散列索引,如下所示,在這種情況下,兩個索引都被創(chuàng)建: 示例 187. 哈希索引與簡單索引一起使用的示例 @Documentpublic class DomainType { @Indexed @HashIndexed String value; // ...} 如果上面的例子過于冗長,復合注解允許減少需要在屬性上聲明的注解數量: 示例 188. 組合哈希索引使用示例 @Documentpublic class DomainType { @IndexAndHash(name = "idx...") String value; // ...}@Indexed@HashIndexed@Retention(RetentionPolicy.RUNTIME) public @interface IndexAndHash { @AliasFor(annotation = Indexed.class, attribute = "name") String name() default ""; } 可能為元注釋的某些屬性注冊別名。 盡管通過注釋創(chuàng)建索引在許多場景中派上用場,但考慮到通過手動設置索引來接管更多控制權IndexOperations。 mongoOperations.indexOpsFor(Jedi.class) .ensureIndex(HashedIndex.hashed("useTheForce")); |
|
來自: 王先生的內容 > 《Spring國際認證》