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

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

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

    Open-Source World

    let's learn and study.
    posts - 28, comments - 23, trackbacks - 0, articles - 1

    Derby入門 —— (1)

    Posted on 2007-09-04 11:04 tearofmoscow 閱讀(1408) 評(píng)論(0)  編輯  收藏
    摘要
           Derby是一個(gè)100%Java開(kāi)源的關(guān)系數(shù)據(jù)庫(kù),并且你不可輕視它。
     
    正文
           一般的應(yīng)用程序都需要一個(gè)簡(jiǎn)單的存儲(chǔ)和獲得數(shù)據(jù)的方法。如果你長(zhǎng)期開(kāi)發(fā)一個(gè)軟件,你都需要一個(gè)關(guān)系數(shù)據(jù)庫(kù)為你長(zhǎng)期服務(wù)。然而,作為一個(gè)Java開(kāi)發(fā)者,你的選擇是有限的。你可能嘗試使用商業(yè)的關(guān)系數(shù)據(jù)庫(kù)管理系統(tǒng),它們大多數(shù)不是用Java語(yǔ)言編寫(xiě)的,雖然普遍的能達(dá)到100% Java JDBC連接器。這些商業(yè)產(chǎn)品通常需要大量的配置,接下來(lái)需要數(shù)據(jù)庫(kù)管理員對(duì)服務(wù)進(jìn)行操作和調(diào)整,并且當(dāng)你在每個(gè)客服端發(fā)布使用時(shí),都需要很高的許可費(fèi)。
           另一方面,你可以選擇一個(gè)開(kāi)源的Java基于關(guān)系數(shù)據(jù)庫(kù)管理系統(tǒng)實(shí)現(xiàn)。這些產(chǎn)品通常是為嵌入式應(yīng)用設(shè)計(jì)的。支持有限的重要的標(biāo)準(zhǔn)SQL語(yǔ)句,并支持關(guān)系數(shù)據(jù)庫(kù)管理系統(tǒng)的最小特性。但是它們是自由許可的,容易管理,并且可以集成一些代碼來(lái)彌補(bǔ)缺少的特性。
           它是一個(gè)理想的,并且開(kāi)源的,100% Java編寫(xiě)的,容易管理的關(guān)系數(shù)據(jù)庫(kù)管理系統(tǒng),它可以和一些商業(yè)產(chǎn)品的特性進(jìn)行交付。這篇文章是關(guān)注Apache Derby項(xiàng)目——一個(gè)兩全其美的關(guān)系數(shù)據(jù)庫(kù)管理系統(tǒng)。
     
    Derby——一個(gè)出神入化的產(chǎn)品周期
           圖片片刻實(shí)現(xiàn)一個(gè)商業(yè)級(jí)軟件產(chǎn)品的完美生命周期。最初,設(shè)計(jì)者應(yīng)該開(kāi)始構(gòu)思;當(dāng)設(shè)計(jì)師不能獲得問(wèn)題的答案或沒(méi)有創(chuàng)新的解決方案時(shí),將會(huì)喪失原有的激情。一旦產(chǎn)品能證明在解決問(wèn)題上有自身的能力,并有一定數(shù)量的用戶基礎(chǔ)后,這個(gè)小公司將進(jìn)入一個(gè)大公司的視野。使這款軟件成為它們收購(gòu)的目標(biāo),大公司將“handen”這個(gè)產(chǎn)品附加質(zhì)量保證,加寬它的范疇,使之快速增長(zhǎng),并寫(xiě)出高質(zhì)量的文檔。一旦這款產(chǎn)品達(dá)到它的最高采用時(shí),然后大公司應(yīng)該支持該產(chǎn)品成為開(kāi)源項(xiàng)目,有一個(gè)很好的自由許可讓每個(gè)人都可以采用和修改。你,作為一個(gè)受益者可以獲得這些健壯的地層代碼,也可以將它加入到你的產(chǎn)品中,商業(yè)應(yīng)用和其他的,并受益于探研地層代碼的所有心血。
           當(dāng)然,上面提到的理想化的軟件產(chǎn)品生命周期聽(tīng)起來(lái)不會(huì)發(fā)生在資本主義自由經(jīng)濟(jì)下。但是有時(shí)在現(xiàn)實(shí)生活中,是做得到的!
           上面理想化的產(chǎn)品生命周期是確切的,因?yàn)樗l(fā)生在Apache Derby上。Derby是一個(gè)名為Cloudscape的小公司構(gòu)思的;當(dāng)Cloudscape賣給Informix后,該產(chǎn)品得到了加強(qiáng);當(dāng)IBM加入時(shí),在“big blue”期間,它的高端工程特性得到增強(qiáng);現(xiàn)在已經(jīng)成為一個(gè)有最自由的許可的開(kāi)源項(xiàng)目而存在。
     
    廣泛而深入的特性列表
           Derby的生動(dòng)逼真的撫育使得它擁有一個(gè)令人驚奇的特性列表。有許多簡(jiǎn)單的高級(jí)特性不能被其他開(kāi)源Java數(shù)據(jù)庫(kù)利用。一部分的列表特性使Derby從其他的Java 關(guān)系數(shù)據(jù)庫(kù)管理系統(tǒng)中分離出來(lái),包括:
    l         100% Java實(shí)現(xiàn)
    l         100% Java類型4 JDBC驅(qū)動(dòng)
    l         SQL92E標(biāo)準(zhǔn)支持大部分SQL 99特性
    l         ACID完全的事務(wù)獨(dú)立的事務(wù)支持
    l         J2EE支持JNDI,連接池和XA
    l         視圖,臨時(shí)表和保存
    l         BLOB和CLOB數(shù)據(jù)類型
    l         行和表鎖定
    l         有價(jià)值的基本查詢優(yōu)化
    l         服務(wù)器端指示約束
    l         觸發(fā)器和存儲(chǔ)過(guò)程
    l         為服務(wù)器端函數(shù),觸發(fā)器或存儲(chǔ)過(guò)程等操作在數(shù)據(jù)庫(kù)里存儲(chǔ)Java代碼
    l         能排除CD-ROM里的只讀數(shù)據(jù)庫(kù)
    l         數(shù)據(jù)的導(dǎo)入和導(dǎo)出
    l         快速數(shù)據(jù)庫(kù)加密選項(xiàng)
    在代碼例子中,你將談究使用指示約束,存儲(chǔ)過(guò)程和在數(shù)據(jù)庫(kù)中存儲(chǔ)Java代碼。
     
    兩種靈活的使用模式
           Derby可以工作在嵌入式模式下,或在完全的客戶端/服務(wù)器模式下。插圖1說(shuō)明在嵌入式模式下的工作原理。
    插圖1:嵌入式模式
           在插圖1里,你可以看到Derby引擎是嵌入在你的應(yīng)用程序里的。當(dāng)工作在嵌入式模式,你的應(yīng)用程序訪問(wèn)數(shù)據(jù)庫(kù)是直接和專有的。這就意味著其他應(yīng)用程序不可能在同一時(shí)間訪問(wèn)該數(shù)據(jù)庫(kù)。嵌入式模式的主要優(yōu)點(diǎn)是不需要進(jìn)行網(wǎng)絡(luò)和服務(wù)器設(shè)置。因?yàn)槟愕膽?yīng)用程序包含了Derby引擎,使用者并不知道你使用了一個(gè)關(guān)系數(shù)據(jù)庫(kù)。
           當(dāng)使用Derby的嵌入式模式時(shí),并沒(méi)有復(fù)雜的配置和特殊的API需要你去學(xué)習(xí)。實(shí)際上,你僅僅需要做:
    1.         確保Derby JARs文件在你的應(yīng)用程序classpath里
    2.         使用嵌入式JDBC驅(qū)動(dòng)
    3.         寫(xiě)數(shù)據(jù)庫(kù)訪問(wèn)代碼到JDBC
     
    這是正確的,Derby根本沒(méi)有特殊的APIs。只需要為你的應(yīng)用程序編碼到JDBC,然后Derby會(huì)為你工作得很好。事實(shí)上,如果你已經(jīng)有了JDBC代碼,而想把代碼轉(zhuǎn)換到Derby嵌入式模式下運(yùn)行是十分容易的。
    如果你使用過(guò)ORACLE,DB2,SQL Server或MySQL,你應(yīng)該對(duì)網(wǎng)絡(luò)模式(客戶端/服務(wù)器模式)的工作原理相當(dāng)熟悉。插圖2說(shuō)明了這個(gè)模型的工作原理
    插圖2:客戶端/服務(wù)器模式
    在插圖2中,一個(gè)獨(dú)立的Java進(jìn)程運(yùn)行作為Derby的網(wǎng)絡(luò)服務(wù)器,通過(guò)網(wǎng)絡(luò)監(jiān)聽(tīng)客戶端的連接。該Derby網(wǎng)絡(luò)服務(wù)器能唯一的訪問(wèn)數(shù)據(jù)庫(kù)存儲(chǔ)器,并能同時(shí)接受多個(gè)客戶端連接。這就允許多個(gè)用戶在同一時(shí)間通過(guò)網(wǎng)絡(luò)方式訪問(wèn)該關(guān)系數(shù)據(jù)庫(kù)管理系統(tǒng)。
    當(dāng)不適合使用嵌入式模式進(jìn)行操作時(shí)(例如:你必須運(yùn)行和管理個(gè)別的服務(wù)器進(jìn)程,或許在不同的機(jī)器上),當(dāng)你需要多用戶訪問(wèn)數(shù)據(jù)庫(kù)時(shí),Derby的客戶端-服務(wù)器模式能提供一個(gè)有效的解決方案。
    在插圖2中,注意客戶端應(yīng)用程序編碼到JDBC。這些不是Derby特有的APIs。事實(shí)上,這個(gè)類似于插圖1里的運(yùn)行在嵌入式下JDBC應(yīng)用程序運(yùn)行在客戶端-服務(wù)器模式的最低配置下。
     
    配置Derby數(shù)據(jù)庫(kù)
    為了完全體會(huì)Derby設(shè)置和使用的好處,你需要自己親身體驗(yàn)它。首先,下載和安裝Derby。然后,確保你的classpath環(huán)境變量包含:
    derby_installation_directory\lib\derby.jar;和derby_installation_directory\lib\derbytools.jar
     
    你也可以編輯提供給你的sp.bat文件,設(shè)置你的Derby安裝目錄,然后運(yùn)行設(shè)置你的classpath。
    一旦你設(shè)置好了classpath,就修改工作目錄。數(shù)據(jù)庫(kù)將被創(chuàng)建在這個(gè)目錄里面。從db\createdb目錄復(fù)制createdb.sql文件到工作目錄。然后,啟動(dòng)命令行界面(執(zhí)行ij)進(jìn)入Derby:
    java org.apache.derby.tools.ij
     
    你也可以使用在batch子目錄下提供的ij.bat,在使用前一定要編輯該批處理文件,添加你的Derby安裝目錄路徑。這樣才能進(jìn)入正確的命令行,使用嵌入式Derby引擎。你看到的提示將與下面的類似:
    ij version 10.0
    ij>
     
           你可以輸入“help”;來(lái)查看可以使用的命令。要?jiǎng)?chuàng)建數(shù)據(jù)庫(kù)和表來(lái)使用,僅僅需要運(yùn)行createdb.sql文件。使用ij命令:
    run ‘createdb.sql’;
     
           run命令將調(diào)用一個(gè)腳本文件并執(zhí)行它里面的Derby命令,類似于Windows的批處理文件。下面顯示的是createdb.sql文件的內(nèi)容。
    connect
                   'jdbc:derby:vsjdb;create=true';
    drop table orders;
    drop table custs;
    create table custs
                   (id char (5) not null,
                                   name char(40) not null,
                                                  primary key(id));
    create table orders
                   (id char(8) not null,
                                   custid char(5) not null,
                                                  total integer,
                                                                 primary key(id,custid));
    insert into custs values (
                   '1', 'John Smith');
    insert into custs values (
                   '2', 'Mary Todd');
    insert into orders values(
                   '0001', '1', 39999);
    insert into orders values(
                   '0002', '1', 2999);
    insert into orders values(
                   '0003', '1', 1904);
    insert into orders values(
                   '0004', '2', 3232);
    insert into orders values(
                   '0005', '2', 109900);
    在每一行都需要一個(gè)分號(hào),這與命令行輸入命令是一樣的。腳本的第一行是連接命令,指明連接的嵌入式Derby驅(qū)動(dòng)名字。在腳本里的連接命令為:
    connect
                  ‘jdbc:derby:vsjdb;create=true’;
     
           使用jdbc:derby說(shuō)明Derby驅(qū)動(dòng)是使用的JDBC協(xié)議,而vsjdb是一個(gè)數(shù)據(jù)庫(kù)的名字,它能通過(guò)嵌入式驅(qū)動(dòng)創(chuàng)建和訪問(wèn)。create=true屬性說(shuō)明如果該數(shù)據(jù)庫(kù)不存在時(shí),就創(chuàng)建該數(shù)據(jù)庫(kù)。
           該createdb.sql腳本將創(chuàng)建一個(gè)名為vsjdb(當(dāng)它不存在時(shí))的數(shù)據(jù)庫(kù),并在該數(shù)據(jù)庫(kù)中創(chuàng)建custs和orders表。它將在表中添加兩個(gè)用戶和五個(gè)定單。如果你使用過(guò)其他數(shù)據(jù)庫(kù)的SQL語(yǔ)句,你應(yīng)該相當(dāng)熟悉在腳本里的SQL語(yǔ)句。
           你可以查看你的工作目錄,現(xiàn)在你將看到一個(gè)vsjdb子目錄。數(shù)據(jù)將保存在里面。數(shù)據(jù)庫(kù)可以很簡(jiǎn)單的的進(jìn)行備份,就是復(fù)制這個(gè)子目錄。
     
    表格1和表格2是custs和orders表的信息
    Table 1: The custs table
    Field Name
    Data Type
    Note
    Id
    char(5)
    primary key
    Name
    char(40)
     
    Table 2: The orders table
    Field Name
    Data Type
    Note
    Id
    char(8)
    primary key (compound)
    Custid
    char(5)
    primary key (compound)
    Total
    int
     
     
    與關(guān)系數(shù)據(jù)庫(kù)管理系統(tǒng)數(shù)據(jù)操作
    要查看顧客記錄信息,在ij提示行后使用SQL SELECT語(yǔ)句:
    select * from custs;
     
    要查看定單,使用下面的命令:
    select * from orders;
     
    要?jiǎng)h除顧客,嘗試使用下面的命令:
    delete from custs where id=’1’;
     
    你可以選擇custs表里的某一行,并能查看到哪個(gè)用戶被刪除。要?jiǎng)h除與這個(gè)用戶相關(guān)聯(lián)的定單信息,使用下面的命令:
    delete from orders where custid=’1’;
     
    你現(xiàn)在可以查看orders表,并能看見(jiàn)所有關(guān)于一號(hào)顧客的定單都被刪除了。
    在你離開(kāi)ij前,刪除數(shù)據(jù)庫(kù)里的所有記錄:
    delete from custs;
    delete from orders;
     
    著它將是一個(gè)空數(shù)據(jù)庫(kù),在下一部分,將寫(xiě)入自定義的Java代碼。
    使用exit命令離開(kāi)ij:
    exit;
     
    自從連接URL指定了嵌入式驅(qū)動(dòng),只有ij能唯一的訪問(wèn)這個(gè)數(shù)據(jù)庫(kù)。
     
    嵌入Derby到你的Java應(yīng)用程序中
           時(shí)間加速我們的Java編譯和編寫(xiě)某些代碼。這些代碼將放入Derby做一個(gè)小測(cè)試,給你一個(gè)關(guān)系數(shù)據(jù)庫(kù)管理系統(tǒng)能處理現(xiàn)實(shí)世界大量數(shù)據(jù)能力的信心。
           下面是名為FillTable.java的代碼,將創(chuàng)建1000個(gè)用戶,每個(gè)用戶有10條定單——總共10000條定單。在嵌入子目錄下你可以找到FillTable.java的源代碼。
    import java.sql.*;
    public class TableFiller {
                   Connection conn = null;
                   PreparedStatement insertCust
                                   = null;
                   PreparedStatement insertOrder
                                   = null;
     
           上面的申明是標(biāo)準(zhǔn)的JDBC申明。conn控制JDBC連接。insertCust和insertOrder將分別處理插入記錄到custs和orders表里的SQL語(yǔ)句。PreparedStatement的使用使關(guān)系數(shù)據(jù)庫(kù)管理系統(tǒng)得到優(yōu)化的可能。
           其次,下面的代碼,driverName包含我們裝載和使用的JDBC驅(qū)動(dòng)器的類名。這是一個(gè)嵌入式驅(qū)動(dòng)器。連接的URL是url值。你可以看見(jiàn)是使用的絕對(duì)路徑定位這個(gè)數(shù)據(jù)庫(kù)(注意:你必須要使用正斜線來(lái)分離路徑)。如果你總是在你的工作目錄運(yùn)行這個(gè)程序的話,你可以僅使用”jdbc:derby:vsjdb”。也可以可以設(shè)置derby.system.home屬性來(lái)改變Derby數(shù)據(jù)庫(kù)文件的位置(例如:java –D derby.system.home=c:\mydbdir org.apche.derby.tools.ij)。
    String driverName =
    "org.apache.derby.jdbc.EmbeddedDriver";
    String url =
                   "jdbc:derby:c:/derby1021/vsjdb";
     
           loadDrivers()方法裝載JDBC驅(qū)動(dòng)類并創(chuàng)建獲得一個(gè)Derby的JDBC連接。并準(zhǔn)備兩個(gè)插入語(yǔ)句。
    public void loadDrivers()
                   throws SQLException,
                   ClassNotFoundException {
                   Class.forName(driverName);
                   conn = DriverManager.getConnection(
                                   url);
                   insertCust = conn.prepareStatement(
                                   "INSERT INTO custs VALUES(
                                   ?, ?)");
                   insertOrder =
                                   conn.prepareStatement(
                                   "INSERT INTO orders VALUES(
                                   ?, ?, ?)");
    }
     
           TableFiller的main()方法創(chuàng)建一個(gè)TableFiller的實(shí)例,并調(diào)用它的addCustomer()方法去創(chuàng)建1000個(gè)用戶。它也調(diào)用addOrder()方法去創(chuàng)建10000條定單信息。為了顯示進(jìn)度,它打印顧客編號(hào)和’.’到系統(tǒng)輸出中。
    public static void main(String args[])
                   throws Exception {
                   TableFiller tf = new TableFiller();
                   tf.loadDrivers();
                   int orderNum = 1;
                   for (int i=1; i<1001>
                                   String custNum = "" + i;
                                   tf.addCustomer(
                                                  custNum, "customer #" + i);
                                   System.out.print("\n"
                                                  + custNum);
                                   for (int j=1; j<11>
                                                  tf.addOrder( ""+ orderNum,
                                                                 custNum, j * 99);
                                                  orderNum++;
                                                  System.out.print(".");
                                   }
                   }
                   tf.closeAll();
    }
     
    addCustomer()方法獲得參數(shù)并執(zhí)行insertCust的預(yù)編譯語(yǔ)句。
    public void addCustomer(
                   String id, String custname)
                   throws SQLException {
                   insertCust.setString(1, id);
                   insertCust.setString(2, custname);
                   insertCust.executeUpdate();
    }
     
    addOrder()方法獲得參數(shù)并執(zhí)行insertOrder的預(yù)編譯語(yǔ)句。
    public void addOrder(String id,
                   String custid, int total)
                   throws SQLException {
                   insertOrder.setString(1, id);
                   insertOrder.setString(2, custid);
                   insertOrder.setInt(3, total);
                   insertOrder.executeUpdate();
    }
     
    closeAll()整理和關(guān)閉兩個(gè)預(yù)編譯語(yǔ)句和JDBC連接,通知Derby釋放被控制的資源。
    public void closeAll()
                   throws SQLException {
                   insertCust.close();
                   insertOrder.close();
                   conn.close();
    }
    }
     
           當(dāng)顧客和定單被創(chuàng)建,程序?qū)⒋蛴☆櫩途幪?hào)到屏幕上。編號(hào)從1到1000表明每個(gè)顧客被創(chuàng)建。而打印的每個(gè)’.’則表明定單被創(chuàng)建。
           要編譯這個(gè)代碼,你僅僅需要確信你已經(jīng)設(shè)置了classpath,并且使用標(biāo)準(zhǔn)的Java編譯命令:
    java TableFiller.java
     
    你要確保沒(méi)有ij或其他Derby會(huì)話在運(yùn)行。在嵌入式模式你需要唯一的訪問(wèn)數(shù)據(jù)庫(kù)。在編譯成功后,需要復(fù)制TableFiller.class文件到你的工作目錄下,然后從那里運(yùn)行TableFiller:
    java TableFiller
     
    你應(yīng)該看見(jiàn)打印出來(lái)的狀態(tài)和寫(xiě)入數(shù)據(jù)庫(kù)的記錄。
     
    檢驗(yàn)被創(chuàng)建的記錄
           現(xiàn)在,去看看你創(chuàng)建的顧客和定單信息,確保你在工作目錄并再次登錄到ij。連接vsjdb數(shù)據(jù)庫(kù)。
    connect ‘jdbc:derby:vsjdb’;
     
    然后使用下面的SELECT語(yǔ)句查看所有1000條顧客信息。
    select * from custs;
     
    同樣的使用下面的SELECT語(yǔ)句查看所有10000條定單信息。
    select * from orders;
     
    當(dāng)然,使用類似于FillTable.java里的標(biāo)準(zhǔn)JDBC代碼,你可以整合Derby的關(guān)系數(shù)據(jù)庫(kù)的訪問(wèn)功能到你的任何一個(gè)工程中。當(dāng)你的項(xiàng)目需要一個(gè)嵌入式數(shù)據(jù)庫(kù)時(shí),有能力簡(jiǎn)單和快速處理產(chǎn)生大量的數(shù)據(jù)的Derby是你最好的選擇。Derby的自由Apache許可允許你綁定它到你的程序上,即使你決定把你的產(chǎn)品進(jìn)行商業(yè)買賣。
     
    探索Derby的高級(jí)特性
           由于Derby是從IBM中分離出來(lái)的,Derby有許多高級(jí)功能——具有代表性的僅僅建立在高端的關(guān)系數(shù)據(jù)庫(kù)管理系統(tǒng)中。插圖3展現(xiàn)了幾個(gè)有趣的特性。
    插圖3:Derby的數(shù)據(jù)庫(kù)特性
           在插圖3中,該數(shù)據(jù)庫(kù)存儲(chǔ)包括數(shù)據(jù)表,圖表,關(guān)系信息——這是所有關(guān)系數(shù)據(jù)庫(kù)所必須有的。另外,你可以看見(jiàn)它也可以包含觸發(fā)器,存儲(chǔ)過(guò)程,甚至Java代碼。這些高級(jí)特性將在文章的后面部分探究。Derby的網(wǎng)絡(luò)模式的操作也將被提及。
     
    配置Derby的網(wǎng)絡(luò)模式
           要訪問(wèn)Derby的網(wǎng)絡(luò)服務(wù)器模式,首先你需要把下面的JAR文件地址添加到你的classpath值里。
    derby_installation_directory\lib\derbynet.jar
     
           你還需要為客戶端訪問(wèn)下載一個(gè)網(wǎng)絡(luò)JDBC驅(qū)動(dòng)。如果你使用IBM DB2 JDBC普通驅(qū)動(dòng),你則需要把下面的JAR文件地址添加到你的classpath值里:
    derby_installation_directory\lib\db2_jcc.jar
    derby_installation_directory\lib\db2_jcc_license_c.jar
     
           batch子目錄里的sp.bat文件里的classpath值已經(jīng)包含了這些JARs文件地址。
           啟動(dòng)網(wǎng)絡(luò)服務(wù)器,使用下面的命令:
    java org.apache.derby.drda.NetworkServerControl start
     
    你也可以使用batch子目錄下的netsvr.bat文件。
    在默認(rèn)情況下,服務(wù)器將監(jiān)聽(tīng)TCP1527端口來(lái)接收客戶端請(qǐng)求。你可以使用”-p ”參數(shù)來(lái)改變端口。
           如果你需要關(guān)閉服務(wù)器,使用下面的命令:
    java org.apache.derby.drda.NetworkServerControl shutdown
     
           或者你可以使用batch子目錄下的netstop.bat文件。
           現(xiàn)在服務(wù)器已經(jīng)準(zhǔn)備好了,為我們下面的探究鋪上了臺(tái)階。

    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 日韩激情无码免费毛片| 免费A级毛片av无码| 亚洲精品成人片在线观看精品字幕 | 国产成人综合亚洲| 亚洲日本va中文字幕久久| 免费A级毛片无码A∨免费| 国产亚洲中文日本不卡二区| 男女交性永久免费视频播放| 国产va免费观看| 亚洲人成在线中文字幕| 四虎影库久免费视频| 中文字幕免费在线观看| 精品熟女少妇aⅴ免费久久| 最新国产成人亚洲精品影院| 国产亚洲3p无码一区二区| 亚洲精品国产精品乱码不99 | 啦啦啦在线免费视频| a级毛片免费全部播放| 中文字幕亚洲码在线| 亚洲国产精品无码久久98| 无码乱人伦一区二区亚洲一| 国产精品免费播放| 无码人妻一区二区三区免费| 国产免费AV片在线观看 | 日韩亚洲欧洲在线com91tv| 亚洲精品一级无码鲁丝片| 久久久久久久久免费看无码| 成人精品一区二区三区不卡免费看| 蜜臀亚洲AV无码精品国产午夜.| 亚洲国产日韩在线人成下载| 中文字幕无码精品亚洲资源网久久| 老子影院午夜伦不卡亚洲| www成人免费观看网站| 美女18一级毛片免费看| 黄色视屏在线免费播放| 91高清免费国产自产拍2021| 欧美男同gv免费网站观看 | 国产精品视频免费观看| 久久国产乱子伦精品免费看| 免费看成人AA片无码视频吃奶| 最好看最新的中文字幕免费|