午夜视频在线网站,日韩视频精品在线,中文字幕精品一区二区三区在线,在线播放精品,1024你懂我懂的旧版人,欧美日韩一级黄色片,一区二区三区在线观看视频

分享

Spring認證中國教育管理中心-Spring Data Couchbase教程二

 王先生的內容 2022-01-10

原標題:Spring認證中國教育管理中心-Spring Data Couchbase教程二(Spring中國教育管理中心)

Spring Data Couchbase教程二

2.1.3一般建議

  • 嘗試堅持使用不可變對象?——不可變對象很容易創(chuàng)建,因為實現對象只需調用其構造函數即可。此外,這可以避免您的域對象被允許客戶端代碼操縱對象狀態(tài)的 setter 方法亂扔垃圾。如果您需要這些,最好將它們包保護起來,以便它們只能被有限數量的并置類型調用。僅構造函數實現比屬性填充快 30%。

  • 提供一個全參數的構造函數?——即使你不能或不想將你的實體建模為不可變值,提供一個將實體的所有屬性作為參數(包括可變屬性)的構造函數仍然有價值,因為這允許對象映射以跳過屬性填充以獲得最佳性能。

  • 使用工廠方法而不是重載的構造函數來避免@PersistenceConstructor?- 使用最佳性能所需的全參數構造函數,我們通常希望公開更多特定于應用程序用例的構造函數,這些構造函數省略自動生成的標識符等內容。這是一種既定的模式,而不是使用靜態(tài)工廠方法來公開這些全參數構造函數的變體。

  • 確保遵守允許使用生成的實例化器和屬性訪問器類的約束?——?

  • 對于要生成的標識符,仍將 final 字段與全參數持久性構造函數(首選)或with…方法結合使用?——?

  • 使用 Lombok 避免樣板代碼?- 由于持久性操作通常需要一個構造函數來獲取所有參數,因此它們的聲明變成了對字段分配的樣板參數的繁瑣重復,使用 Lombok 可以最好地避免這種情況@AllArgsConstructor。

覆蓋屬性

Java 允許靈活設計域類,其中子類可以定義一個已在其超類中以相同名稱聲明的屬性。考慮以下示例:

public class SuperType {   private CharSequence field;   public SuperType(CharSequence field) {      this.field = field;
   }   public CharSequence getField() {      return this.field;
   }   public void setField(CharSequence field) {      this.field = field;
   }
}public class SubType extends SuperType {   private String field;   public SubType(String field) {      super(field);      this.field = field;
   }   @Override
   public String getField() {      return this.field;
   }   public void setField(String field) {      this.field = field;      // optional
      super.setField(field);
   }
}

Spring Data Couchbase教程二

這兩個類都定義了一個fieldusing 可分配類型。SubType然而陰影SuperType.field。根據類設計,使用構造函數可能是設置的唯一默認方法SuperType.field?;蛘?,調用super.setField(…)setter 可以設置fieldin SuperType。所有這些機制都會在某種程度上產生沖突,因為屬性共享相同的名稱但可能代表兩個不同的值。如果類型不可分配,Spring Data 會跳過超類型屬性。也就是說,被覆蓋的屬性的類型必須可以分配給它的超類型屬性類型才能注冊為覆蓋,否則超類型屬性被認為是瞬態(tài)的。我們通常建議使用不同的屬性名稱。

Spring Data 模塊通常支持覆蓋不同值的屬性。從編程模型的角度來看,有幾點需要考慮:

  1. 應該保留哪個屬性(默認為所有聲明的屬性)?您可以通過使用 注釋這些屬性來排除屬性@Transient。

  2. 如何在數據存儲中表示屬性?對不同的值使用相同的字段/列名稱通常會導致數據損壞,因此您應該使用明確的字段/列名稱注釋至少一個屬性。

  3. @AccessType(PROPERTY)不能使用 using ,因為如果不對 setter 實現進行任何進一步的假設,通常無法設置超屬性。

2.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)建新對象實例的方法,該方法從現有對象復制所有屬性值并將作為參數提供的屬性值應用到該方法。

Kotlin 覆蓋屬性

Kotlin 允許聲明屬性覆蓋以更改子類中的屬性。

open class SuperType(open var field: Int)class SubType(override var field: Int = 1) :
	SuperType(field) {
}

這樣的安排呈現了兩個名為 的屬性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;
   }
}

Spring Data Couchbase教程二

getter 和 setterSubType僅在set 上SubType.field,而不在SuperType.field. 在這種安排中,使用構造函數是 set 的唯一默認方法SuperType.field。添加一個方法來SubType設置
SuperType.fieldviathis.SuperType.field = …是可能的,但不屬于支持的約定。屬性覆蓋在某種程度上會產生沖突,因為屬性共享相同的名稱但可能代表兩個不同的值。我們通常建議使用不同的屬性名稱。

Spring Data 模塊通常支持覆蓋不同值的屬性。從編程模型的角度來看,有幾點需要考慮:

  1. 應該保留哪個屬性(默認為所有聲明的屬性)?您可以通過使用 注釋這些屬性來排除屬性@Transient。

  2. 如何在數據存儲中表示屬性?對不同的值使用相同的字段/列名稱通常會導致數據損壞,因此您應該使用明確的字段/列名稱注釋至少一個屬性。

  3. @AccessType(PROPERTY)由于無法設置超屬性,因此無法使用 using 。

2.2.文檔和字段

所有實體都應使用注釋進行@Document注釋,但這不是必需的。

此外,實體中的每個字段都應使用注釋進行@Field注釋。雖然這是 - 嚴格來說 - 可選的,但它有助于減少邊緣情況并清楚地顯示實體的意圖和設計。它還可以用于以不同的名稱存儲字段。

還有一個特殊的@Id注釋需要始終到位。最佳做法是同時命名屬性 id。

這是一個非常簡單的User實體:

示例 6. 帶有字段的簡單文檔

import org.springframework.data.annotation.Id;import org.springframework.data.couchbase.core.mapping.Field;import org.springframework.data.couchbase.core.mapping.Document;@Documentpublic class User {    @Id
    private String id;    @Field
    private String firstname;    @Field
    private String lastname;    public User(String id, String firstname, String lastname) {        this.id = id;        this.firstname = firstname;        this.lastname = lastname;
    }    public String getId() {        return id;
    }    public String getFirstname() {        return firstname;
    }    public String getLastname() {        return lastname;
    }
}

Spring Data Couchbase教程二

Couchbase Server 支持文檔自動過期。該庫通過@Document注釋實現對它的支持。您可以設置一個expiry值,該值轉換為文檔被自動刪除之前的秒數。如果你想讓它在突變后 10 秒內過期,請將其設置為@Document(expiry = 10). 或者,您可以使用 Spring 的屬性支持和expiryExpression參數配置到期,以允許動態(tài)更改到期值。例如:@Document(expiryExpression = "${valid.document.expiry}")。該屬性必須可解析為 int 值,并且不能混合使用這兩種方法。

如果您想要文檔中的字段名稱與實體中使用的字段名稱不同的表示形式,您可以在@Field注釋上設置不同的名稱。例如,如果您想保持文檔較小,您可以將 firstname 字段設置為@Field("fname")。在JSON文件,你會看到{"fname": ".."},而不是{"firstname": ".."}。

在@Id注釋中需要存在,因為Couchbase每個文件需要一個唯一的密鑰。該鍵必須是長度不超過 250 個字符的任意字符串。隨意使用適合您用例的任何內容,無論是 UUID、電子郵件地址還是其他任何內容。

2.3.數據類型和轉換器

選擇的存儲格式是 JSON。這很棒,但與許多數據表示一樣,它允許的數據類型比您直接用 Java 表達的要少。因此,對于所有非原始類型,需要進行某種形式的與支持類型之間的轉換。

對于以下實體字段類型,無需添加特殊處理:

Spring Data Couchbase教程二

由于JSON支持對象(“映射”)和列表,Map和List類型可以自然被轉換。如果它們只包含最后一段中的原始字段類型,則您也不需要添加特殊處理。這是一個例子:

示例 7. 帶有地圖和列表的文檔

@Documentpublic class User {    @Id
    private String id;    @Field
    private List<String> firstnames;    @Field
    private Map<String, Integer> childrenAges;    public User(String id, List<String> firstnames, Map<String, Integer> childrenAges) {        this.id = id;        this.firstnames = firstnames;        this.childrenAges = childrenAges;
    }

}

用一些示例數據存儲用戶可能看起來像這樣的 JSON 表示:

示例 8. 帶有地圖和列表的文檔 - JSON

{    "_class": "foo.User",    "childrenAges": {        "Alice": 10,        "Bob": 5
    },    "firstnames": [        "Foo",        "Bar",        "Baz"
    ]
}

您不需要一直將所有內容分解為原始類型和列表/映射。當然,您也可以用這些原始值組合其他對象。讓我們修改最后一個示例,以便我們要存儲 a Listof Children:

示例 9. 包含組合對象的文檔

@Documentpublic class User {    @Id
    private String id;    @Field
    private List<String> firstnames;    @Field
    private List<Child> children;    public User(String id, List<String> firstnames, List<Child> children) {        this.id = id;        this.firstnames = firstnames;        this.children = children;
    }

    static class Child {        private String name;        private int age;

        Child(String name, int age) {            this.name = name;            this.age = age;
        }

    }

}

填充的對象可能如下所示:

示例 10. 包含組合對象的文檔 - JSON

{  "_class": "foo.User",  "children": [
    {      "age": 4,      "name": "Alice"
    },
    {      "age": 3,      "name": "Bob"
    }
  ],  "firstnames": [    "Foo",    "Bar",    "Baz"
  ]
}

大多數情況下,您還需要存儲一個時間值,例如 a Date。由于它不能直接存儲在 JSON 中,因此需要進行轉換。該庫實現默認的轉換器Date,Calendar以及JodaTime類型(如果在classpath)。所有這些在文檔中默認表示為一個 unix 時間戳(數字)。您始終可以使用自定義轉換器覆蓋默認行為,如下所示。這是一個例子:

示例 11. 帶有日期和日歷的文檔

@Documentpublic class BlogPost {    @Id
    private String id;    @Field
    private Date created;    @Field
    private Calendar updated;    @Field
    private String title;    public BlogPost(String id, Date created, Calendar updated, String title) {        this.id = id;        this.created = created;        this.updated = updated;        this.title = title;
    }

}

填充的對象可能如下所示:

示例 12. 帶有日期和日歷的文檔 - JSON

{  "title": "a blog post title",  "_class": "foo.BlogPost",  "updated": 1394610843,  "created": 1394610843897}

可選地,可以通過將系統(tǒng)屬性設置
org.springframework.data.couchbase.useISOStringConverterForDate為 true來將日期轉換為符合 ISO-8601 的字符串。如果您想覆蓋轉換器或實現自己的轉換器,這也是可能的。該庫實現了一般的 Spring Converter 模式。您可以在配置中的 bean 創(chuàng)建時間插入自定義轉換器。這是您可以配置它的方法(在您的覆蓋中AbstractCouchbaseConfiguration):

示例 13. 自定義轉換器

@Overridepublic CustomConversions customConversions() {    return new CustomConversions(Arrays.asList(FooToBarConverter.INSTANCE, BarToFooConverter.INSTANCE));
}@WritingConverterpublic static enum FooToBarConverter implements Converter<Foo, Bar> {
    INSTANCE;    @Override
    public Bar convert(Foo source) {        return /* do your conversion here */;
    }

}@ReadingConverterpublic static enum BarToFooConverter implements Converter<Bar, Foo> {
    INSTANCE;    @Override
    public Foo convert(Bar source) {        return /* do your conversion here */;
    }

}

自定義轉換需要注意以下幾點:

  • 為了明確起見,請始終在轉換器上使用@WritingConverter和@ReadingConverter注釋。特別是如果您正在處理原始類型轉換,這將有助于減少可能的錯誤轉換。

  • 如果你實現了一個寫入轉換器,請確保只解碼為原始類型、映射和列表。如果您需要更復雜的對象類型,請使用CouchbaseDocument和CouchbaseList類型,底層翻譯引擎也可以理解這些類型。您最好的選擇是堅持盡可能簡單的轉換。

  • 始終在通用轉換器之前放置更多特殊轉換器,以避免執(zhí)行錯誤轉換器的情況。

  • 對于日期,讀取轉換器應該能夠從任何Number(不僅僅是Long)讀取。這是 N1QL 支持所必需的。

    本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯系方式、誘導購買等信息,謹防詐騙。如發(fā)現有害或侵權內容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多