<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Dict.CN 在線詞典, 英語學(xué)習(xí), 在線翻譯

    都市淘沙者

    荔枝FM Everyone can be host

    統(tǒng)計

    留言簿(23)

    積分與排名

    優(yōu)秀學(xué)習(xí)網(wǎng)站

    友情連接

    閱讀排行榜

    評論排行榜

    高級 DAO 編程

    內(nèi)容:
    DAO 基礎(chǔ)
    事務(wù)界定
    使用 JDBC 進(jìn)行事務(wù)界定
    JTA 概述
    使用 JTA 的事務(wù)界定
    用于事務(wù)控制的 JTA 方法
    使用 JTA 和 JDBC
    選擇最好的方式
    日志記錄和 DAO
    DAO 中的異常處理
    實(shí)現(xiàn)實(shí)例:MovieDAO
    結(jié)束語
    參考資料
    關(guān)于作者
    對本文的評價
    相關(guān)內(nèi)容:
    使用 SDAO 進(jìn)行 J2EE 測試的分步方法
    Create persistent application data with Java Data Objects
    理解 JTS -- 事務(wù)處理簡介
    developerWorks Toolbox subscription
    Java 專區(qū)中還有:
    教學(xué)
    工具與產(chǎn)品
    代碼與組件
    所有文章
    實(shí)用技巧
    1.2學(xué)習(xí)編譯更好的 DAO 的技巧
    Sean C. Sullivan (dao-article@seansullivan.com)
    J2EE 開發(fā)人員使用數(shù)據(jù)訪問對象(Data Access Object DAO)設(shè)計模式,以便將低級別的數(shù)據(jù)訪問邏輯與高級別的業(yè)務(wù)邏輯分離。實(shí)現(xiàn) DAO 模式涉及比編寫數(shù)據(jù)訪問代碼更多的內(nèi)容。在本文中,Java 開發(fā)人員 Sean C. Sullivan 討論了 DAO 編程中三個常常被忽略的方面:事務(wù)界定、異常處理和日志記錄。

    在過去 18 個月中,我參加了一個由有才華的軟件工程師組成的小組,構(gòu)建定制的、基于 Web 的供應(yīng)鏈管理應(yīng)用程序。我們的應(yīng)用程序訪問范圍廣泛的持久性數(shù)據(jù),包括配送狀態(tài)、供應(yīng)鏈衡量(metrics)、庫存、貨運(yùn)發(fā)票、項(xiàng)目管理數(shù)據(jù)和用戶信息。我們用 JDBC API 連接到我們公司的不同數(shù)據(jù)庫平臺上,并在整個應(yīng)用程序中使用 DAO 設(shè)計模式。

    圖 1 顯示了應(yīng)用程序和數(shù)據(jù)源之間的關(guān)系:

    圖 1. 應(yīng)用程序和數(shù)據(jù)源
    應(yīng)用程序和數(shù)據(jù)源

    在整個應(yīng)用程序中使用數(shù)據(jù)訪問對象(DAO)使我們可以將底層數(shù)據(jù)訪問邏輯與業(yè)務(wù)邏輯分離開來。我們構(gòu)建了為每一個數(shù)據(jù)源提供 GRUD (創(chuàng)建、讀取、更新、刪除)操作的 DAO 類。

    在本文中,我將為您介紹構(gòu)建更好的 DAO 類的 DAO 實(shí)現(xiàn)策略和技術(shù)。更確切地說,我將討論日志、異常處理和事務(wù)界定。您將學(xué)到如何將這三者結(jié)合到自己的 DAO 類中。本文假定您熟悉 JDBC API、SQL 和關(guān)系數(shù)據(jù)庫編程。

    我們將以對 DAO 設(shè)計模式和數(shù)據(jù)訪問對象的概述開始。

    DAO 基礎(chǔ)
    DAO 模式是標(biāo)準(zhǔn) J2EE 設(shè)計模式之一。開發(fā)人員用這種模式將底層數(shù)據(jù)訪問操作與高層業(yè)務(wù)邏輯分離開。一個典型的 DAO 實(shí)現(xiàn)有以下組件:

    • 一個 DAO 工廠類
    • 一個 DAO 接口
    • 一個實(shí)現(xiàn)了 DAO 接口的具體類
    • 數(shù)據(jù)傳輸對象(有時稱為值對象)

    具體的 DAO 類包含訪問特定數(shù)據(jù)源的數(shù)據(jù)的邏輯。在下面一節(jié)中您將學(xué)習(xí)設(shè)計和實(shí)現(xiàn)數(shù)據(jù)訪問對象的技術(shù)。有關(guān) DAO 設(shè)計模式的更多內(nèi)容請參閱 參考資料

    事務(wù)界定
    關(guān)于 DAO 要記住的重要一點(diǎn)是它們是事務(wù)性對象。由 DAO 所執(zhí)行的每一個操作 -- 如創(chuàng)建、更新或者刪除數(shù)據(jù) -- 都與一個事務(wù)相關(guān)聯(lián)。因此,事務(wù)界定的概念就變得特別重要了。

    事務(wù)界定是定義事務(wù)邊界的方式。J2EE 規(guī)范描述了兩種事務(wù)界定的模型:編程式(programmatic)和聲明式(declarative)。表 1 分析了這兩種模型:

    表 1. 兩種事務(wù)界定的模型
    聲明式事務(wù)界定 編程式事務(wù)界定
    程序員用 EJB 部署描述符聲明事務(wù)屬性。 程序員負(fù)責(zé)編寫事務(wù)邏輯。
    運(yùn)行時環(huán)境(EJB 容器)用這些屬性自動管理事務(wù)。 應(yīng)用程序通過一個 API 控制事務(wù)。

    我們將側(cè)重于編程式事務(wù)界定。

    設(shè)計考慮
    如前所述,DAO 是事務(wù)性對象。一個典型的 DAO 執(zhí)行像創(chuàng)建、更新和刪除這樣的事務(wù)性操作。在設(shè)計 DAO 時,首先要問自己以下問題:

    • 事務(wù)要如何開始?
    • 事務(wù)應(yīng)如何結(jié)束?
    • 哪一個對象將負(fù)責(zé)開始一個事務(wù)?
    • 哪一個對象將負(fù)責(zé)結(jié)束一個事務(wù)?
    • DAO 是否要負(fù)責(zé)事務(wù)的開始和結(jié)束?
    • 應(yīng)用程序是否需要通過多個 DAO 訪問數(shù)據(jù)?
    • 事務(wù)涉及到一個 DAO 還是多個 DAO?
    • 一個 DAO 是否調(diào)用另一個 DAO 的方法?

    了解上述問題的答案將有助于您選擇最適合的 DAO 的事務(wù)界定策略。在 DAO 中有兩種主要的界定事務(wù)的策略。一種方式是讓 DAO 負(fù)責(zé)界定事務(wù),另一種將事務(wù)界定交給調(diào)用這個 DAO 方法的對象處理。如果選擇了前一種方式,那么就將事務(wù)代碼嵌入到 DAO 中。如果選擇后一種方式,那么事務(wù)界定代碼就是在 DAO 類外面。我們將使用簡單的代碼示例幫助您更好理解每一種方式是如何工作的。

    清單 1 顯示了一個有兩種數(shù)據(jù)操作的 DAO:創(chuàng)建和更新:

    清單 1. DAO 方法
      public void createWarehouseProfile(WHProfile profile); public void updateWarehouseStatus(WHIdentifier id, StatusInfo status); 

    清單 2 顯示了一個簡單的事務(wù)。事務(wù)界定在 DAO 類外面。注意在這個例子中調(diào)用者是如何在一個事務(wù)中結(jié)合多個 DAO 操作的。

    清單 2. 調(diào)用者管理的事務(wù)
      tx.begin(); // start the transaction dao.createWarehouseProfile(profile); dao.updateWarehouseStatus(id1, status1); dao.updateWarehouseStatus(id2, status2); tx.commit(); // end the transaction 

    這種事務(wù)界定策略對于需要在一個事務(wù)中訪問多個 DAO 的應(yīng)用程序特別有用。

    可以用 JDBC API 或者 Java 事務(wù) API(Java Transaction API JTA)實(shí)現(xiàn)事務(wù)界定。 JDBC 事務(wù)界定比 JTA 事務(wù)界定要簡單,但是 JTA 提供了更多的靈活性。在下面一節(jié)中我將更深入地分析事務(wù)界定的機(jī)制。

    用 JDBC 進(jìn)行事務(wù)界定
    JDBC 事務(wù)是用 Connection 對象控制的。JDBC Connection 接口(java.sql.Connection)提供了兩種事務(wù)模式:自動提交和手工提交。java.sql.Connection 提供了以下控制事務(wù)的方法:

    • public void setAutoCommit(boolean)
    • public boolean getAutoCommit()
    • public void commit()
    • public void rollback()

    清單 3 顯示了如何用 JDBC API 界定一個事務(wù):

    清單 3. 用 JDBC API 進(jìn)行事務(wù)界定
      import java.sql.*; import javax.sql.*; // ... DataSource ds = obtainDataSource(); Connection conn = ds.getConnection(); conn.setAutoCommit(false); // ... pstmt = conn.prepareStatement("UPDATE MOVIES ..."); pstmt.setString(1, "The Great Escape"); pstmt.executeUpdate(); // ... conn.commit(); // ... 

    使用 JDBC 事務(wù)界定時,您可以將多個 SQL 語句結(jié)合到一個事務(wù)中。JDBC 事務(wù)的一個缺點(diǎn)是事務(wù)的范圍局限于一個數(shù)據(jù)庫連接。一個 JDBC 事務(wù)不能跨越多個數(shù)據(jù)庫。在下面,我們將看一下如何用 JTA 進(jìn)行事務(wù)界定。因?yàn)?JTA 不像 JDBC 那樣有名,所以我們首先做一個簡介。

    JTA 簡介
    Java 事務(wù) API(JTA) 及其同門兄弟 Java 事務(wù)服務(wù)(Java Transaction Service JTS)為 J2EE 平臺提供了分布式事務(wù)服務(wù)。一個分布式的事務(wù)涉及一個事務(wù)管理器和一個或者多個資源管理器。一個資源管理器是任何類型的持久性的數(shù)據(jù)存儲。事務(wù)管理器負(fù)責(zé)協(xié)調(diào)所有事務(wù)參與者之間的通信。事務(wù)管理器與資源管理器之間的關(guān)系如圖 2 所示:

    圖 2. 一個事務(wù)管理器和資源管理器
    一個事務(wù)管理器和資源管理器

    JTA 事務(wù)比 JDBC 事務(wù)功能更強(qiáng)。JDBC 事務(wù)局限為一個數(shù)據(jù)庫連接,而 JTA 事務(wù)可以有多個參與者。所有下列 Java 平臺組件都可以參與 JTA 事務(wù):

    • JDBC 連接
    • JDO PersistenceManager 對象
    • JMS 隊(duì)列
    • JMS 主題
    • 企業(yè) JavaBeans
    • 符合 J2EE 連接體系結(jié)構(gòu)(J2EE Connector Architecture)規(guī)范的資源適配器

    使用 JTA 的事務(wù)界定
    要用 JTA 進(jìn)行事務(wù)界定,應(yīng)用程序要調(diào)用 javax.transaction.UserTransaction 接口中的方法。清單 4 顯示了對 UserTransaction 對象的典型 JNDI 查詢:

    清單 4. 一個對 UserTransaction 對象的 JDNI 查詢
      import javax.transaction.*; import javax.naming.*; // ... InitialContext ctx = new InitialContext(); Object txObj = ctx.lookup("java:comp/UserTransaction"); UserTransaction utx = (UserTransaction) txObj; 

    當(dāng)應(yīng)用程序找到了 UserTransaction 對象后,就可以開始事務(wù)了,如清單 5 所示:

    清單 5. 用 JTA 開始一個事務(wù)
      utx.begin(); // ... DataSource ds = obtainXADataSource(); Connection conn = ds.getConnection(); pstmt = conn.prepareStatement("UPDATE MOVIES ..."); pstmt.setString(1, "Spinal Tap"); pstmt.executeUpdate(); // ... utx.commit(); // ... 

    當(dāng)應(yīng)用程序調(diào)用 commit()時,事務(wù)管理器用一個兩階段的提交協(xié)議結(jié)束事務(wù)。

    控制事務(wù)的 JTA 方法
    javax.transaction.UserTransaction 接口提供了以下事務(wù)控制方法:

    • public void begin()
    • public void commit()
    • public void rollback()
    • public int getStatus()
    • public void setRollbackOnly()
    • public void setTransactionTimeout(int)

    應(yīng)用程序調(diào)用 begin() 開始事務(wù)。應(yīng)用程序調(diào)用 commit() 或者 rollback() 結(jié)束事務(wù)。參閱參考資料以了解更多關(guān)于用 JTA 進(jìn)行事務(wù)管理的內(nèi)容。

    使用 JTA 和 JDBC
    開發(fā)人員通常在 DAO 類中用 JDBC 進(jìn)行底層數(shù)據(jù)操作。如果計劃用 JTA 界定事務(wù),那么就需要有一個實(shí)現(xiàn) javax.sql.XADataSourcejavax.sql.XAConnection javax.sql.XAResource 接口的 JDBC 驅(qū)動程序。一個實(shí)現(xiàn)了這些接口的驅(qū)動程序?qū)⒖梢詤⑴c JTA 事務(wù)。一個 XADataSource 對象就是一個 XAConnection 對象的工廠。XAConnections 是參與 JTA 事務(wù)的 JDBC 連接。

    您將需要用應(yīng)用服務(wù)器的管理工具設(shè)置 XADataSource。從應(yīng)用服務(wù)器和 JDBC 驅(qū)動程序的文檔中可以了解到相關(guān)的指導(dǎo)。

    J2EE 應(yīng)用程序用 JNDI 查詢數(shù)據(jù)源。一旦應(yīng)用程序找到了數(shù)據(jù)源對象,它就調(diào)用 javax.sql.DataSource.getConnection() 以獲得到數(shù)據(jù)庫的連接。

    XA 連接與非 XA 連接不同。一定要記住 XA 連接參與了 JTA 事務(wù)。這意味著 XA 連接不支持 JDBC 的自動提交功能。同時,應(yīng)用程序一定不要對 XA 連接調(diào)用 java.sql.Connection.commit() 或者 java.sql.Connection.rollback()。相反,應(yīng)用程序應(yīng)該使用 UserTransaction.begin()、UserTransaction.commit() serTransaction.rollback()

    選擇最好的方式
    我們討論了如何用 JDBC 和 JTA 界定事務(wù)。每一種方式都有其優(yōu)點(diǎn),您需要決定哪一種最適合于您的應(yīng)用程序。

    在最近的許多項(xiàng)目中,我們小組是用 JDBC API 進(jìn)事務(wù)界定來構(gòu)建 DAO 類的。這些 DAO 類可以總結(jié)如下:

    • 事務(wù)界定代碼嵌入在 DAO 類中。
    • DAO 類使用 JDBC API 進(jìn)行事務(wù)界定。
    • 調(diào)用者不能界定事務(wù)。
    • 事務(wù)范圍局限于單個 JDBC 連接。

    JDBC 事務(wù)并不總是適合復(fù)雜的企業(yè)應(yīng)用程序。如果您的事務(wù)要跨越多個 DAO 或者多個數(shù)據(jù)庫,那么下列實(shí)現(xiàn)策略也許更合適:

    • 事務(wù)用 JTA 界定。
    • 事務(wù)界定代碼從 DAO 中分離出來。
    • 調(diào)用者負(fù)責(zé)界定事務(wù)。
    • DAO 加入一個全局事務(wù)。

    JDBC 方式由于其簡單性而具有吸引力,JTA 方式提供了更大的靈活性。您所選擇的實(shí)現(xiàn)將取決于應(yīng)用程序的特定需求。

    日志記錄和 DAO
    一個良好實(shí)現(xiàn)的 DAO 類將使用日志記錄來捕捉有關(guān)其運(yùn)行時行為的細(xì)節(jié)。您可以選擇記錄異常、配置信息、連接狀態(tài)、JDBC 驅(qū)動程序元數(shù)據(jù)、或者查詢參數(shù)。日志對于開發(fā)的所有階段都很有用。我經(jīng)常在開發(fā)時、測試時和生產(chǎn)中分析應(yīng)用程序日志。

    在本節(jié),我將展示一個顯示如何將 Jakarta Commons Logging 加入到 DAO 中的代碼示例。在這之前,讓我們回顧一下一些基本知識。

    選擇日志庫
    許多開發(fā)人員使用一種原始格式進(jìn)行日志記錄:System.out.println System.err.printlnPrintln 語句速度快且使用方便,但是它們沒有提供全功能的日志記錄系統(tǒng)所具有的功能。表 2 列出了 Java 平臺的日志庫:

    表 2. Java 平臺的日志庫
    日志庫 開放源代碼? URL
    java.util.logging 不是 http://java.sun.com/j2se/
    Jakarta Log4j http://jakarta.apache.org/log4j/
    Jakarta Commons Logging http://jakarta.apache.org/commons/logging.html

    java.util.logging 是 J2SE 1.4 平臺上的標(biāo)準(zhǔn) API。不過,大多數(shù)開發(fā)人員同意 Jakarta Log4j 提供了更多的功能和更大的靈活性。Log4j 優(yōu)于 java.util.logging 的一點(diǎn)是它同時支持 J2SE 1.3 和 J2SE 1.4 平臺。

    Jakarta Commons Logging 可以與 java.util.logging 或者 Jakarta Log4j 一同使用。Commons Logging 是一個日志抽象層,它隔離了應(yīng)用程序與底層日志實(shí)現(xiàn)。使用 Commons Logging,您可以通過改變配置文件更換底層日志實(shí)現(xiàn)。Commons Logging 在 Jakarta Struts 1.1 和 Jakarta HttpClient 2.0 中使用。

    一個日志記錄示例
    清單 7 顯示了如何在 DAO 類中使用 Jakarta Commons Logging:

    清單 7. DAO 類中的 Jakarta Commons Logging
     import org.apache.commons.logging.*; class DocumentDAOImpl implements DocumentDAO { static private final Log log = LogFactory.getLog(DocumentDAOImpl.class); public void deleteDocument(String id) { // ... log.debug("deleting document: " + id); // ... try { // ... data operations ... } catch (SomeException ex) { log.error("Unable to delete document", ex); // ... handle the exception ... } } } 

    日志記錄是所有任務(wù)關(guān)鍵型應(yīng)用程序的重要部分。如果在 DAO 中遇到故障,那么日志通常可以提供判斷出錯位置的最好信息。將日志加入到 DAO 可以保證您有機(jī)會進(jìn)行調(diào)試和故障排除。

    DAO 中的異常處理
    我們討論過了事務(wù)界定和日志,現(xiàn)在對于如何在數(shù)據(jù)訪問對象上應(yīng)用它們有了更深入的理解。我們的第三個和最后一個討論議題是異常處理。遵從幾個簡單的異常處理指導(dǎo)可以使您的 DAO 更容易使用、更健壯及更易于維護(hù)。

    在實(shí)現(xiàn) DAO 模式時,考慮以下問題:

    • DAO 的公共接口中的方法是否拋出檢查過的異常?
    • 如果是的話,拋出何種檢查過的異常?
    • 在 DAO 實(shí)現(xiàn)類中如何處理異常?

    在使用 DAO 模式的過程中,我們的小組開發(fā)了一些處理異常的原則。遵從這些原則可以極大地改進(jìn)您的 DAO:

    • DAO 方法應(yīng)該拋出有意義的異常。

    • DAO 方法不應(yīng)該拋出 java.lang.Exceptionjava.lang.Exception 太一般化了。它不傳遞關(guān)于底層問題的任何信息。

    • DAO 方法不應(yīng)該拋出 java.sql.SQLException。SQLException 是一個低級別的 JDBC 異常。一個 DAO 應(yīng)該力爭封裝 JDBC 而不是將 JDBC 公開給應(yīng)用程序的其余部分。

    • 只有在可以合理地預(yù)期調(diào)用者可以處理異常時,DAO 接口中的方法才應(yīng)該拋出檢查過的異常。如果調(diào)用者不能以有意義的方式處理這個異常,那么考慮拋出一個未檢查的(運(yùn)行時)異常。

    • 如果數(shù)據(jù)訪問代碼捕獲了一個異常,不要忽略它。忽略捕獲的異常的 DAO 是很難進(jìn)行故障診斷的。

    • 使用鏈接的異常將低級別的異常轉(zhuǎn)化為高級別的異常。

    • 考慮定義標(biāo)準(zhǔn) DAO 異常類。Spring Framework (參閱參考資料)提供了很好的一套預(yù)定義的 DAO 異常類。

    有關(guān)異常和異常處理技術(shù)的更多信息參閱參考資料

    實(shí)現(xiàn)實(shí)例: MovieDAO
    MovieDAO 是一個展示本文中討論的所有技術(shù)的 DAO:事務(wù)界定、日志和異常處理。您可以在參考資料一節(jié)中找到 MovieDAO 源代碼。代碼分為三個包:

    • daoexamples.exception
    • daoexamples.movie
    • daoexamples.moviedemo

    DAO 模式的這個實(shí)現(xiàn)包含下面列出的類和接口:

    • daoexamples.movie.MovieDAOFactory
    • daoexamples.movie.MovieDAO
    • daoexamples.movie.MovieDAOImpl
    • daoexamples.movie.MovieDAOImplJTA
    • daoexamples.movie.Movie
    • daoexamples.movie.MovieImpl
    • daoexamples.movie.MovieNotFoundException
    • daoexamples.movie.MovieUtil

    MovieDAO 接口定義了 DAO 的數(shù)據(jù)操作。這個接口有五個方法,如下所示:

    • public Movie findMovieById(String id)
    • public java.util.Collection findMoviesByYear(String year)
    • public void deleteMovie(String id)
    • public Movie createMovie(String rating, String year, String, title)
    • public void updateMovie(String id, String rating, String year, String title)

    daoexamples.movie 包包含 MovieDAO 接口的兩個實(shí)現(xiàn)。每一個實(shí)現(xiàn)使用一種不同的方式進(jìn)行事務(wù)界定,如表 3 所示:

    表 3. MovieDAO 實(shí)現(xiàn)
    MovieDAOImpl MovieDAOImplJTA
    實(shí)現(xiàn) MovieDAO 接口?
    通過 JNDI 獲得 DataSource?
    從 DataSource 獲得 java.sql.Connection 對象?
    DAO 在內(nèi)部界定事務(wù)?
    使用 JDBC 事務(wù)?
    使用一個 XA DataSource?
    參與 JTA 事務(wù)?

    MovieDAO 演示應(yīng)用程序
    這個演示應(yīng)用程序是一個名為 daoexamples.moviedemo.DemoServlet 的 servlet 類。DemoServlet 使用這兩個 Movie DAO 查詢和更新表中的電影數(shù)據(jù)。

    這個 servlet 展示了如何將支持 JTA 的 MovieDAO 和 Java 消息服務(wù)(Java Message Service)結(jié)合到一個事務(wù)中,如清單 8 所示。

    清單 8. 將 MovieDAO 和 JMS 代碼結(jié)合到一個事務(wù)中
      UserTransaction utx = MovieUtil.getUserTransaction(); utx.begin(); batman = dao.createMovie("R", "2008", "Batman Reloaded"); publisher = new MessagePublisher(); publisher.publishTextMessage("I'll be back"); dao.updateMovie(topgun.getId(), "PG-13", topgun.getReleaseYear(), topgun.getTitle()); dao.deleteMovie(legallyblonde.getId()); utx.commit(); 

    要運(yùn)行這個演示應(yīng)用程序,需要在應(yīng)用服務(wù)器上配置一個 XA 數(shù)據(jù)源和一個非 XA 數(shù)據(jù)源。然后,部署 daoexamples.ear 文件。這個應(yīng)用程序可以在任何兼容 J2EE 1.3 的應(yīng)用服務(wù)器上運(yùn)行。參閱參考資料以獲得 EAR 文件和源代碼。

    結(jié)束語
    正如本文所展示的,實(shí)現(xiàn) DAO 模式需要做比編寫低級別的數(shù)據(jù)訪問代碼更多的工作。現(xiàn)在,通過選擇一個適合您的應(yīng)用程序的事務(wù)界定策略、通過在 DAO 類中加入日志記錄,以及通過遵從幾項(xiàng)簡單的異常處理原則,您可以構(gòu)建更好的 DAO。

    參考資料

    posted on 2006-02-22 20:29 都市淘沙者 閱讀(342) 評論(0)  編輯  收藏 所屬分類: PatterDesign/UML/Rose/ERwin

    主站蜘蛛池模板: 在线观看免费污视频| 亚洲人成电影在线天堂| 三上悠亚电影全集免费| 亚洲熟妇无码久久精品| 又粗又大又长又爽免费视频| 免费看成人AA片无码视频吃奶| 亚洲国产精品张柏芝在线观看| 国产精品色午夜免费视频| 你懂的在线免费观看| 日韩亚洲产在线观看| 亚洲日韩欧洲无码av夜夜摸| 国产又黄又爽又猛免费app| 亚洲免费在线观看| 国产成人亚洲精品| 亚洲国产成人高清在线观看 | 亚洲精品乱码久久久久久蜜桃| 一级毛片在线免费观看| 亚洲AV日韩综合一区| 久久精品国产亚洲av水果派| 日韩亚洲国产综合久久久| 国产91免费视频| 精品一区二区三区免费| 国产精品手机在线亚洲| 亚洲AV综合色区无码二区爱AV| 亚洲熟妇无码AV在线播放| 日本最新免费不卡二区在线| 亚洲三级在线免费观看| 久久WWW免费人成—看片| 亚洲狠狠婷婷综合久久蜜芽| 亚洲精品熟女国产| 久久亚洲综合色一区二区三区| 国产免费131美女视频| www.999精品视频观看免费| 波多野结衣免费一区视频| 一级做a爰片性色毛片免费网站| 激情综合亚洲色婷婷五月| 亚洲一区二区电影| 亚洲s色大片在线观看| JLZZJLZZ亚洲乱熟无码| 国产又黄又爽又刺激的免费网址| 18勿入网站免费永久|