一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

Spring認證中國教育管理中心-Spring Data MongoDB教程十三

 王先生的內容 2021-11-29

原標題: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;
   }
}

Spring認證中國教育管理中心-Spring Data MongoDB教程十三

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

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

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

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

  3. using@AccessType(PROPERTY)不能使用,因為不能設置超級屬性。

18.2.基于約定的映射

MappingMongoConverter當沒有提供額外的映射元數據時,有一些將對象映射到文檔的約定。這些約定是:

  • 簡短的 Java 類名稱以下列方式映射到集合名稱。該類com.bigbank.SavingsAccount映射到savingsAccount集合名稱。

  • 所有嵌套對象都作為嵌套對象存儲在文檔中,而不是作為 DBRef 存儲。

  • 轉換器使用任何注冊的 Spring 轉換器來覆蓋對象屬性到文檔字段和值的默認映射。

  • 對象的字段用于在文檔中的字段之間進行轉換。JavaBean不使用公共屬性。

  • 如果您有一個非零參數構造函數,其構造函數參數名稱與文檔的頂級字段名稱匹配,則使用該構造函數。否則,將使用零參數構造函數。如果有多個非零參數構造函數,則會拋出異常。

18.2.1._id在映射層中如何處理字段。

MongoDB 要求您有一個_id包含所有文檔的字段。如果您不提供,驅動程序將分配一個帶有生成值的 ObjectId。“_id”字段可以是除數組以外的任何類型,只要它是唯一的。驅動程序自然支持所有原始類型和日期。使用 時,MappingMongoConverter有一些規(guī)則控制 Java 類中的屬性如何映射到此_id字段。

以下概述了將映射到_id文檔字段的字段:

  • 帶有@Id( org.springframework.data.annotation.Id)注釋的字段將映射到該_id字段。

  • 沒有注釋但已命名id的_id字段將映射到該字段。

  • 標識符的默認字段名稱是_id并且可以通過@Field注釋進行自定義。

Spring認證中國教育管理中心-Spring Data MongoDB教程十三

下面概述了對映射到 _id 文檔字段的屬性進行的類型轉換(如果有)。

  • 如果id在 Java 類中將命名字段聲明為 String 或 BigInteger,則將盡可能將其轉換為 ObjectId 并存儲為 ObjectId。ObjectId 作為字段類型也是有效的。如果您id在應用程序中指定了一個值,那么 MongoDB 驅動程序會檢測到 ObjectId 的轉換。如果指定的id值無法轉換為 ObjectId,則該值將按原樣存儲在文檔的 _id 字段中。如果該字段用 注釋,這也適用@Id。

  • 如果一個字段@MongoId在 Java 類中被注釋,它將被轉換為并存儲為使用它的實際類型。除非@MongoId聲明所需的字段類型,否則不會發(fā)生進一步的轉換。

  • 如果一個字段@MongoId(FieldType.…)在 Java 類中被注釋,它將嘗試將值轉換為聲明的FieldType.

  • 如果名為idid 字段的字段未在 Java 類中聲明為 String、BigInteger 或 ObjectID,那么您應該在應用程序中為其分配一個值,以便它可以“按原樣”存儲在文檔的 _id 字段中。

  • 如果idJava 類中不存在已命名的字段_id,則驅動程序將生成一個隱式文件,但不會映射到 Java 類的屬性或字段。

查詢和更新時MongoTemplate將使用轉換器來處理與上述保存文檔規(guī)則相對應的Query和Update對象的轉換,因此查詢中使用的字段名稱和類型將能夠匹配域類中的內容。

18.3.數據映射和類型轉換

本節(jié)解釋了類型如何映射到 MongoDB 表示和從 MongoDB 表示映射。Spring Data MongoDB 支持所有可以表示為 BSON(MongoDB 的內部文檔格式)的類型。除了這些類型之外,Spring Data MongoDB 還提供了一組內置轉換器來映射其他類型。您可以提供自己的轉換器來調整類型轉換。有關更多詳細信息,請參閱[
mapping-explicit-converters]。

下面提供了每種可用類型轉換的示例:

Spring認證中國教育管理中心-Spring Data MongoDB教程十三

Spring認證中國教育管理中心-Spring Data MongoDB教程十三

Spring認證中國教育管理中心-Spring Data MongoDB教程十三

Spring認證中國教育管理中心-Spring Data MongoDB教程十三

18.4.映射配置

除非明確配置,否則MappingMongoConverter在創(chuàng)建MongoTemplate. 您可以創(chuàng)建自己的MappingMongoConverter. 這樣做可以讓您指定在類路徑中可以找到域類的位置,以便 Spring Data MongoDB 可以提取元數據并構建索引。此外,通過創(chuàng)建您自己的實例,您可以注冊 Spring 轉換器以將特定類映射到數據庫或從數據庫映射。

您可以使用基于 Java 或基于 XML 的元數據來配置MappingMongoConverter以及
com.mongodb.client.MongoClientMongoTemplate。以下示例使用 Spring 的基于 Java 的配置:

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認證中國教育管理中心-Spring Data MongoDB教程十三


AbstractMongoClientConfiguration要求您實現(xiàn)定義 acom.mongodb.client.MongoClient以及提供數據庫名稱的方法。AbstractMongoClientConfiguration還有一個名為的方法getMappingBasePackage(…),您可以重寫該方法以告訴轉換器在哪里掃描使用@Document注釋注釋的類。

您可以通過覆蓋該
customConversionsConfiguration方法向轉換器添加其他轉換器。MongoDB 的原生 JSR-310 支持可以通過MongoConverterConfigurationAdapter.useNativeDriverJavaTimeCodecs(). 前面的示例中還顯示了一個LoggingEventListener,它記錄MongoMappingEvent了發(fā)布到 SpringApplicationContextEvent基礎設施上的實例。


AbstractMongoClientConfiguration創(chuàng)建一個MongoTemplate實例并將其注冊到名稱為 的容器中mongoTemplate。

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>

Spring認證中國教育管理中心-Spring Data MongoDB教程十三

該base-package屬性告訴它在哪里掃描用@
org.springframework.data.mongodb.core.mapping.Document注釋注釋的類。

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 可以使用元數據來驅動對象到文檔的映射。以下注釋可用:

  • @Id:應用于字段級別以標記用于標識目的的字段。

  • @MongoId:應用于字段級別以標記用于標識目的的字段。接受一個可選FieldType的自定義 id 轉換。

  • @Document: 應用于類級別,表示該類是映射到數據庫的候選。您可以指定將存儲數據的集合的名稱。

  • @DBRef:應用于該字段以指示將使用 com.mongodb.DBRef 存儲它。

  • @DocumentReference: 應用于該字段以指示它將被存儲為指向另一個文檔的指針。這可以是單個值(默認為id),也可以是Document通過轉換器提供的值。

  • @Indexed: 應用于字段級別,描述如何索引字段。

  • @CompoundIndex (可重復):在類型級別應用以聲明復合索引。

  • @GeoSpatialIndexed:應用于字段級別以描述如何對字段進行地理索引。

  • @TextIndexed: 在字段級別應用,用于標記要包含在文本索引中的字段。

  • @HashIndexed:在字段級別應用以在散列索引中使用以跨分片集群對數據進行分區(qū)。

  • @Language: 在字段級別應用以設置文本索引的語言覆蓋屬性。

  • @Transient: 默認情況下,所有字段都映射到文檔。此注釋將應用它的字段排除在數據庫中。瞬態(tài)屬性不能在持久性構造函數中使用,因為轉換器無法實現(xiàn)構造函數參數的值。

  • @PersistenceConstructor: 標記給定的構造函數 - 即使是受包保護的構造函數 - 在從數據庫實例化對象時使用。構造函數參數按名稱映射到檢索到的文檔中的鍵值。

  • @Value:這個注解是 Spring Framework 的一部分。在映射框架內,它可以應用于構造函數參數。這使您可以使用 Spring 表達式語言語句來轉換在數據庫中檢索到的鍵值,然后再使用它來構造域對象。為了引用給定文檔的屬性,必須使用如下表達式:@Value("#root.myProperty")whereroot指的是給定文檔的根。

  • @Field:應用于字段級別,它允許描述字段的名稱和類型,因為它將在 MongoDB BSON 文檔中表示,從而允許名稱和類型與類的字段名稱以及屬性類型不同。

  • @Version:應用于字段級別用于樂觀鎖定并檢查保存操作的修改。初始值是zero(one對于原始類型),它會在每次更新時自動觸發(fā)。

映射元數據基礎設施在一個獨立的 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。用于構造函數參數的值按以下方式解析:

  • 如果參數用注釋進行@Value注釋,則計算給定的表達式并將結果用作參數值。

  • 如果 Java 類型具有名稱與輸入文檔的給定字段匹配的屬性,則使用它的屬性信息選擇適當的構造函數參數以將輸入字段值傳遞給。這僅在 java.class文件中存在參數名稱信息時才有效,這可以通過使用調試信息編譯源代碼或使用-parametersJava 8 中 javac的新命令行開關來實現(xiàn)。

  • 否則MappingException將拋出 a 指示無法綁定給定的構造函數參數。

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可以在
MappingMongoConverterUnitTests測試套件中找到使用注釋的其他示例。

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"));

    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    六月丁香六月综合缴情| 久久这里只精品免费福利| 欧美日韩人妻中文一区二区 | 国产日产欧美精品视频| 欧洲一区二区三区蜜桃| 丰满熟女少妇一区二区三区| 欧美日韩人妻中文一区二区| 东京热一二三区在线免| 最好看的人妻中文字幕| 在线播放欧美精品一区| 麻豆最新出品国产精品| 欧美日本道一区二区三区| 极品熟女一区二区三区| 日本乱论一区二区三区| 成人精品日韩专区在线观看| 成人欧美精品一区二区三区 | 国产精品亚洲精品亚洲| 婷婷基地五月激情五月| 欧美偷拍一区二区三区四区| 91人妻人人做人碰人人九色| 欧美日韩国产免费看黄片| 日韩一区二区三区观看| 欧美精品一区二区三区白虎| 中文字幕日韩欧美亚洲午夜 | 东京热加勒比一区二区三区| 大香蕉网国产在线观看av| 国产传媒精品视频一区| 亚洲av熟女国产一区二区三区站| 嫩草国产福利视频一区二区| 国产又猛又黄又粗又爽无遮挡| 国产一区二区在线免费| 老司机精品视频在线免费| 国产黑人一区二区三区| 精品人妻少妇二区三区| 国产av精品高清一区二区三区| 国产精品亚洲欧美一区麻豆| 成年女人午夜在线视频| 91精品国产品国语在线不卡 | 中文字幕欧美精品人妻一区| 国产欧美日产中文一区| 欧美一区二区三区播放|