亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

使用DB4O對象數據庫進行簡單持久化

2019-11-18 12:37:37
字體:
來源:轉載
供稿:網友

  許多的java程序都需要處理持久性數據,在大多數的情況下,需要和關系數據庫打交道,可能是遺留數據庫或是一個工業標準的數據庫治理系統(DBMS)。JDBC 的API和驅動為大多數的數據庫系統提供了一個使用SQL語言進行查詢的標準方式,然而,在對象模型應用程序和關系模型的數據庫的領域之間,“錯誤匹配問題”使得接口程序十分復雜。對象模型是基于軟件工程的原理和業務領域的對象模型,而關系模型是基于數學原理和數據庫有效存取規則。兩種模型沒有誰比誰更好,問題是兩者是不同的,并不總能在程序中有效協調工作。
  
  對于這個問題已經有一些解決方案,例如Hibernate和Java Data Objects,他們為開發者提供了透明的持久性——應用程序只需使用面向對象的API處理持久性的對象,而不需要在Java代碼中嵌入SQL語句。對于EJB的容器來說,容器治理的持久性(CMP)做了類似的工作,但是對Java平臺來說這不是一個一般的持久性工具。在任何這些解決方案中,對象通過底層框架被映射關系數據庫中的表,這些底層的框架生成SQL所需要存取的對象的屬性。也就是說,對象模型越復雜,這種映射就越困難。我們所用的描述符,通常使用xml文件,來定義這種映射關系。繼續和多對多的關系,尤其是一些關系模型無法直接表示的關系增加了映射復雜度。繼續的結構可以有不同的方式被映射到一組表中,選擇何種方式就需要在儲存的效率和查詢的復雜度上權衡,就如一個單獨的表要實現一個多對多的關系一樣。
  
  在一個數據庫中存儲一個對象,數據庫本身假如就是一個對象模型,這樣,就提供了另外一個解決方案。在二十世紀九十年代,各種各樣面向對象的數據庫治理系統被開發出來,但是這些數據庫配置十分復雜,而且需要使用對象定義語言。對象是作為對象格式存儲的,但是對應用語言來說它們不是本地化的。目前這些數據庫產品并沒對市場有大的影響,只是和一些將關系和對象混雜的數據庫一樣,在關系數據庫面向對象的API上下功夫。
  
  嵌入式數據庫
  
  在一些應用中,數據庫治理系統的維護費用是必不可少的,在一些小功耗,可嵌入的數據庫引擎條件下,可以更好的提供數據庫的存儲需求,例如,SQLite,提供了一個自我包含的數據庫引擎。但是,因為這個JAVA的接口是通過一個JDBC驅動,這種以SQL為基礎的解決方案也存在“錯誤匹配問題”。
  
  在許多案例中,持久性問題可以變得相當的簡單,假如使用嵌入式的對象數據庫引擎話。這是一個很好的機會,我們來了解一下Carl Rosenberg創建的db4o。db4o曾經是一個商業的對象數據庫,現在它是開源的,而且,最近獲得了GPL(GNU通用公共許可證)的許可證。
  
  Db4o的功能特點:
  ●    沒有錯誤匹配問題——對象以其本身方式來存儲
  ●    自動治理數據模式
  ●    存儲時沒有改變類特征,以使得易于存儲
  ●    與Java(.NET)無縫綁定
  ●    自動數據綁定
  ●    一個250Kb的庫文件的簡易安裝(Java jar or .NET DLL)
  ●    一個數據庫文件
  ●    自動模式版本
  ●    查詢實例
  ●    S.O.D.A. (簡單對象數據庫訪問), 一個開源查詢的API
  
  Db4o的優點
  
  Db4o已經被一些嵌入式系統的應用程序所選用,這些程序特點都是要求零治理、高可靠性和低功耗的。例如,在德國,BMW Car IT在汽車嵌入式系統電子原型中使用了它。同樣是德國的Die Mobilanten,他們在中型公共事業的PDA解決方案中使用了db4o。在美國,Massie Systems為嬰兒眼睛診斷的視網膜圖像處理系統依靠db4o加強其客戶交流圖像數據庫。
  
  在db4o中存儲對象的方式相當的簡單,同時,對于教學目的來說也相當具有吸引力。艾塞克斯(英)大學和德州農工大學都把db4o作為教學和研究對象。在我自己的學院,對于那些需要如何要將面向對象的概念應用到他們的項目中去的學生,和關系數據庫打交道對于他們設計自己領域內的模型來說是一個負面的影響。使用db4o可以使得他們只需和持久層的數據打交道而不需要分心處理一個相沖突的不理解的數據關系模型,也不需要花費更多的時間學習一個工具,如Hibernate或一個復雜的OODBMS。同時,學習面向對象查詢API的概念可能在將來被證實更有效。
  
  同樣的API,不同的存儲
  
  有時候,你正好不得不使用一個關系數據庫。從一個Java開發者的觀點來看,透明的持久性是理想境界。假如持久性可以通過面向對象的API實現,那么開發者就不必要為不同的數據存儲來學習不同的技術。盡管db4o不是JDO兼容的(作為一個結果很輕易使用),它的創造者的伙伴們有許多其他的開源項目,包括MySQL和Hibernate,它們使用單一的、一致的對象持久性的API和對象數據庫交互,包括db4o本身,一些關系數據庫或者其他存儲模式,例如PRevayler。假如JDO對于你來說比較重要,你可以考慮ObjectDB,它是一個JDO兼容的純對象數據庫.
  
  一個例子
  
  這個例子演示了創建一個數據庫和存儲對象是如何簡單。它同時演示了兩種查詢的方法:實例查詢和更具有彈性的S.O.D.A查詢API。整個的源代碼在文章主題資源的部分可以下載[實際上對資源這部分不是合適的下載地方]。為了可以運行,你必須在你的路徑里添加db4o jar文件并且執行Db4oTest.java。
  
  在實例中有兩個類,分別代表棒球隊(Team)和成員(Player)。為了使得例子更加有趣,我們還有一個投手的類(Pitcher),Pitcher是Player的一個子類。并且添加了一個額外的數據域在Pitcher中。Team類有一個屬性,就是該team的成員(player)列表,它當然包括Pitcher對象。Team、Player、Pitcher對象是一些簡單傳統的Java對象,這里并沒有持久層的代碼。也不需要有唯一的要害字屬性,當一個對象數據庫在自動存儲對象時是需要唯一對象標識符(OIDS)。
  
  Player class
  public class Player {                                                                          protected String name;
  protected int squadNumber;
  protected float battingAverage;
  protected Team team;                                                                        public Player(String name, int squadNumber,                      float battingAverage){
  this.name = name;
  this.squadNumber = squadNumber;
  
  this.battingAverage = battingAverage;
  }                                                                                  public void setName(String n){this.name = n;}                   public String getName(){return this.name;}
  public void setSquadNumber(int s){this.squadNumber = s;}
  public int getSquadNumber(){return this.squadNumber;}
  public void setBattingAverage(final float b) {
  this.battingAverage = b; }
  public float getBattingAverage(){
  return this.battingAverage;}                                                                  public void setTeam(Team t) {this.team = t;}                   public Team getTeam() {return this.team;}
  public String toString() {
  return name + ":" + battingAverage;
  }
  }
  
  Pitcher class
  public class Pitcher extends Player{
  
  private int wins;
  
  public Pitcher(String name, int squadNumber,
  float battingAverage, int wins) {
  super(name,squadNumber,battingAverage);
  this.wins = wins;
  }
  public void setWins(final int w){this.wins = w;}
  public int getWins() {return this.wins;}
  public String toString() {
  return name + ":" + battingAverage + ", " + wins;
  }
  }
  
  Team class
  import java.util.List;
  import java.util.ArrayList;
  public class Team {
  private String name;
  private String city;
  
  private int won;
  
  private int lost;
  private List players;
  public Team(String name, String city,
  int won, int lost){
  this.name = name;
  this.city = city;
  this.won = won;
  this.lost = lost;
  this.players = new ArrayList();
  }
  public void addPlayer(Player p) {
  players.add(p);
  }
  public void setName(String n){this.name = n;}
  public String getName(){return this.name;}
  
  public void setStadium(String c){this.city = c;}
  public String getCity(){return this.city;}
  public void setPlayers(List p){players = p;}
  public List getPlayers(){return players;}
  public void setWon(int w) {this.won = w;}
  public int getWon(){return this.won;}
  public void setLost(int l) {this.lost = l;}
  public int getLost() {return this.lost;}
  public String toString() {
  return name;
  }
  }
  
  首先,我們來建立一些測試數據。
  
  // Create Players                                              Player p1 = new Player("Barry Bonds", 25, 0.362f);                       Player p2 = new Player("Marquis Grissom", 9, 0.279f);
  Player p3 = new Player("Ray Durham", 5, 0.282f);
  Player p4 = new Player("Adrian Beltre", 29, 0.334f);
  Player p5 = new Player("Cesar Izturis", 3, 0.288f);
  Player p6 = new Player("Shawn Green", 15, 0.266f);
  // Create Pitchers                                              Player p7 = new Pitcher("Kirk Rueter",46, 0.131f, 9);
  Player p8 = new Pitcher("Kazuhisa Ishii",17, 0.127f, 13);
  // Create Teams
  Team t1 = new Team("Giants", "San Francisco", 91, 71);
  Team t2 = new Team("Dodgers", "Los Angeles", 93, 69);
  // Add Players to Teams
  t1.addPlayer(p1); p1.setTeam(t1);
  t1.addPlayer(p2); p2.setTeam(t1);
  t1.addPlayer(p3); p3.setTeam(t1);
  t2.addPlayer(p4); p4.setTeam(t2);
  t2.addPlayer(p5); p5.setTeam(t2);
  t2.addPlayer(p6); p6.setTeam(t2);
  // Add Pitchers to Teams
  t1.addPlayer(p7); p7.setTeam(t1);
  t2.addPlayer(p8); p8.setTeam(t2);
  
  存儲數據
  
  一個Team的對象可以用一行代碼執行存儲操作:
  db.set(t1);
  
  這兒,db是一個指向ObjectContainer對象的一個引用,它在打開一個新數據文件時被創建,如下:
  
  ObjectContainer db = Db4o.openFile(filename);
  
  一個db4o數據庫是一個以.yap為擴展名的文件,其中set方法用來存儲一個對象。
  
  注重這里是存儲了一個Team的對象,并且它包含了Player的對象。我們能夠通過取回Player對象來測試是否存儲了這些Player的對象。最簡單的方法就是用QBE來查詢。
  
  實例查詢的簡單查詢
  
  下面的代碼列出了所有與實例對象匹配的Player對象,這里它們是唯一的。通過調用ObjectContainer的get方法,結果以ObjectSet的方式返還。
  
  Player examplePlayer = new Player("Barry Bonds",0,0f);
  ObjectSet result=db.get(examplePlayer);                                                               System.out.println(result.size());
  while(result.hasNext()) {
  System.out.println(result.next());
  }
  
  同時,我們也可以得到所有我們預先虛構的,創建并存儲的Player對象(所有數據域為0或者是空),如下:
  
  Player examplePlayer = new Player(null,0,0f);
  ObjectSet result=db.get(examplePlayer);                                                      System.out.println(result.size());
  while(result.hasNext()) {
  System.out.println(result.next());
  }
  
  結果如下:
  
  8
  Kazuhisa Ishii:0.127, 13
  Shawn Green:0.266
  Cesar Izturis:0.288
  Adrian Beltre:0.334
  Kirk Rueter:0.131, 9
  Ray Durham:0.282
  Marquis Grissom:0.279
  Barry Bonds:0.362
  
  注重:我們可以取回所有的Player類的對象,包括其子類(這里是Pitcher類)的對象,而不需要任何額外的代價。上面結果中所示的Pitcher對象它們額外的信息(wins)也同樣被取回來了。而在關系數據庫中我們必須知道如何在表中映射繼續樹,可能不得不要加一些額外的表來取回對象所有的屬性。
  
  更新和刪除
  
  更新一個對象可以混合使用上面的方法技術。下面的代碼假定了只有一個結果匹配,并且這個匹配的對象可以上溯到Player,這樣可以保證它的屬性能得到修改。
  
  Player examplePlayer = new Player("Shawn Green",0,0f);
  ObjectSet result = db.get(examplePlayer);
  Player p = (Player) result.next();
  p.setBattingAverage(0.299f);
  db.set(p);
  
  數據庫的對象也可以以同樣的方式被刪除。
  
  Player examplePlayer = new Player("Ray Durham",0,0f);
  ObjectSet result = db.get(examplePlayer);
  Player p = (Player) result.next();
  db.delete(p);
  
  功能更強的查詢
  
  在早期版本的db4o中一個主要的缺點就是實例查詢提供相當有限的查詢能力。例如,你不能像這樣查詢“所有平均擊球率大于30%的隊員”?,F在,db4o包含了S.O.D.A的API可以使得查詢的能力接近SQL。一個Query類的實例代表了含有約束條件的標準查詢圖中的一個節點,這個節點可以代表一個類,或者多個類,或者一個類屬性。
  
  下面的代碼演示了如何執行這樣的操作。我們定義了一個查詢圖的節點并且指定/限制它為Player類。這意味著查詢的返回結果為Player對象。然后,我們向下具體化這張圖,去查找一個節點,代表屬性“平均擊球率”,限制其大于0.3。最后,執行查詢操作,返回數據庫中所有滿足條件的對象。
  
  Query q = db.query();
  q.constrain(Player.class);
  q.descend("battingAverage").constrain(new Float(0.3f)).greater();
  ObjectSet result = q.execute();
  
  初一看,這個查詢操作很類似SQL的查詢,就如這樣:
  
  SELECT * FROM players WHERE battingAverage > 0.3
  
  然而,Player類的設計答應在Team對象和Player之間有相互引用關系,正如測試中的數據。一個Team的對象有一個應用指向一個序列的Player對象,同時每一個Player對象都有一個Team的引用。這就意味這查詢的結果應該包含Player和Team的對象。演示代碼如下:
  
  System.out.println(result.size());
  while(result.hasNext()) {
  // Print Player
  Player p = (Player) result.next();
  System.out.println(p);
  // Getting Player also gets Team - print Team
  Team t = p.getTeam();
  System.out.println(t);
  }
  
  輸出:
  
  2
  Adrian Beltre:0.334
  Dodgers
  Barry Bonds:0.362
  Giants
  
  現在的查詢十分類似SQL語言查詢,如下:
  
  SELECT teams.name, players.name, players.battingAverage FROM teams,  players
  WHERE teams.teamID = players.playerID
  AND battingAverage > 0.3
  
  這個能正常工作是因為相互引用關系已經被設計到對象模型中。對象數據庫是具有可以導航性的:你只要根據預定義的關系就可以取回數據。從另一方面講,關系數據庫并不能直接在表中連接。所以,這樣對于特定查詢更具有彈性的。然而,在給定對象關系中,從對象數據庫中取回對象的關系幾乎不要任何的程序代價。數據庫模型和應用程序對象模型是一致的,所以不需要程序員考慮數據的差異性。假如對象在內存里的時候,你可以從一個給定的Player中得到它所屬的Team,你就可以在對象數據庫中做同樣事。
  
  S.O.D.A.其他功能
  
  SQL查詢答應結果按要求排序,S.O.D.A.也可以達到同樣功效。下面是一個例子演示了取回我們開始存儲的Player對象,并以“平均擊球率”排序。(很顯然,這樣可以知道哪些是投手)
  
  Query q = db.query();                                       q.constrain(Player.class);                                       q.descend("battingAverage").orderAscending();
  ObjectSet result = q.execute();
  
  結果:
  
  7
  Kazuhisa Ishii:0.127, 13
  Kirk Rueter:0.131, 9
  Marquis Grissom:0.279
  Cesar Izturis:0.288
  Shawn Green:0.299
  Adrian Beltre:0.334
  Barry Bonds:0.362
  
  S.O.D.A.可以定義更加復雜的查詢,一旦你除去考慮關系數據庫的方式思考它,那將十分的簡單。為了設置限制條件,你只需根據查詢圖導航,去尋找你想設置條件的類或屬性。查詢圖概念和對象模型領域關系十分緊密。這些對開發者理解十分有益。另一方面,為了達到類似SQL的查詢結果,你必須考慮如何映射對象領域和關系數據的表格。
  
  下面的例子演示了如何在Player類的兩個屬性上設置條件。我們將去查找這樣的隊員:他的擊球率大于0.130,而且他是一個贏過五次以上的投手。另外,我們定義了一個查詢圖節點,限制它為Player類,然后,我們具體化這張圖去尋找一個節點代表屬性“平均擊球率”,使其大于0.13,這個結果是一個Constraint的對象。為了設置下一個限制條件,我們具體化去尋找節點代表屬性“贏”,這本身就意味著是去查找一個Pticher類對象。這個節點的限制條件是大于5,然后使用邏輯與——“AND”操作前一個Constraint對象。
  
  Query q = db.query();
  q.constrain(Player.class);
  Constraint constr =
  q.descend("battingAverage").constrain(
  new Float(0.13f)).greater();
  q.descend("wins").constrain(
  new Integer(5)).greater().and(constr);
  result = q.execute();
  
  結果:
  
  1
  Kirk Rueter:0.131, 9
  Giants
  
  最后一個例子演示了如何組合不同類的屬性作為查詢條件。我們將查詢滿足如下條件的隊員:他的擊球率大于0.300并且他的球隊已經贏了92場以上。最簡單的方式是從Player類開始,然后導航到Team。我們可以和前面一樣具體化去查找“平均擊球率”節點,然后,生成一個Constraint對象。然后,具體化去查找Team的屬性的時候,這個屬性是Team的,而這個節點代表的是Team類,因此,我們可以再次具體化去查找一個節點代表“贏”的Team的贏得屬性,然后生成Constraint對象,最后,我們與前一個Constraint對象與操作即可。
  
  Query q = db.query();
  q.constrain(Player.class);
  Constraint constr =
  q.descend("battingAverage").constrain(
  new Float(0.3f)).greater();
  q.descend("team").descend("won").constrain(
  new Integer(92)).smaller().and(constr);
  result = q.execute();
  
  結果:
  
  1
  Barry Bonds:0.362
  Giants
  
  結論
  
  一個低功耗、可嵌入的對象數據庫提供了一個十分簡單、間接的方法處理對象的持久性。Db4o現在是一個開源的對象數據庫。它擁有一系列很具有吸引力的特點,同時支持Java和.Net。簡單的安裝,同時在對象模型和數據模型間不存在“錯誤匹配問題”。這些使得db4o無論在商業上還是教育上都有廣泛的應用。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲精品电影在线观看| 91国语精品自产拍在线观看性色| 亚洲欧美日韩国产成人| 久久国产精品网站| 免费成人高清视频| 91欧美日韩一区| 久久6精品影院| 51精品国产黑色丝袜高跟鞋| 久久精品成人欧美大片| 这里精品视频免费| 亚洲免费精彩视频| 成人激情在线播放| 欧美激情精品在线| 91中文在线观看| 波霸ol色综合久久| 久久成人在线视频| 中文在线资源观看视频网站免费不卡| 久精品免费视频| 97在线日本国产| 久久久久成人网| 亚洲精品www久久久| 一区二区日韩精品| 亚洲成人亚洲激情| 亚洲欧美日韩综合| 成人国产亚洲精品a区天堂华泰| 中文字幕久热精品在线视频| 久久成人亚洲精品| 一区二区三区四区精品| 国产日韩欧美电影在线观看| 欧美电影在线观看| 亚洲乱码一区av黑人高潮| 国产精品精品视频| 成人精品一区二区三区| 久久国产精品网站| 亚洲理论片在线观看| 欧美最猛性xxxxx(亚洲精品)| 欧美性生交大片免费| 久久久精品国产网站| 亚洲成人中文字幕| 精品国产欧美成人夜夜嗨| 国产日韩精品综合网站| 日本亚洲精品在线观看| 国产精品美女久久| 日韩一区二区精品视频| 一本大道亚洲视频| 成人激情综合网| 亚洲天堂男人天堂| 裸体女人亚洲精品一区| 精品久久久国产| 三级精品视频久久久久| 欧美精品videossex88| 狠狠躁天天躁日日躁欧美| 日本久久久久久久久| 欧美日韩亚洲天堂| 国产精品青青在线观看爽香蕉| 国产精品午夜视频| 国产精品高潮呻吟久久av野狼| 国产精品一区二区三区久久久| 欧美性理论片在线观看片免费| 午夜精品久久久久久久99热浪潮| 岛国av在线不卡| 欧美日韩亚洲91| 日韩在线欧美在线国产在线| 成人在线播放av| 国产精品旅馆在线| 亚洲精品天天看| 久久久噜噜噜久久| 一区二区福利视频| 51视频国产精品一区二区| 国产亚洲美女精品久久久| 欧美国产欧美亚洲国产日韩mv天天看完整| 日韩最新中文字幕电影免费看| 亚洲精品v天堂中文字幕| 国产精品永久免费视频| 欧美富婆性猛交| 欧美小视频在线| 少妇高潮久久久久久潘金莲| 亚洲视频在线播放| 日韩精品免费综合视频在线播放| 欧美日韩裸体免费视频| 亚洲人成亚洲人成在线观看| 欧美一区在线直播| 国产精品国产三级国产aⅴ9色| 中文字幕日韩精品有码视频| 欧美福利视频网站| 国产欧美日韩视频| 久久精品99无色码中文字幕| 91手机视频在线观看| 国产精品高潮粉嫩av| 亚洲最新av网址| 日韩av片永久免费网站| 午夜精品久久久久久久99热| 欧美精品久久久久久久| 国产成+人+综合+亚洲欧美丁香花| 成人欧美一区二区三区在线湿哒哒| 欧美日韩国产成人在线观看| 亚洲精品网址在线观看| 亚洲一区二区三区777| 精品久久中文字幕久久av| 久久av红桃一区二区小说| 久久久久久com| 欧美乱大交做爰xxxⅹ性3| 国产精品偷伦一区二区| 欧美寡妇偷汉性猛交| 亚洲一区二区三区在线免费观看| 国产日韩欧美夫妻视频在线观看| 一区二区欧美在线| 久久久久中文字幕2018| 久久亚洲春色中文字幕| 国产成人jvid在线播放| 最近中文字幕mv在线一区二区三区四区| 538国产精品一区二区在线| 国产精品十八以下禁看| 91精品国产91久久久久福利| 色婷婷综合成人av| 精品国产一区二区三区四区在线观看| 久久久www成人免费精品| 欧美激情videos| 亚洲一区二区少妇| 国产欧美精品日韩| 欧美久久精品一级黑人c片| 亚洲欧美中文在线视频| 欧美激情免费观看| 亚洲男人天堂2019| 中文精品99久久国产香蕉| 日韩国产欧美精品在线| 国产欧美日韩精品在线观看| 91国语精品自产拍在线观看性色| 精品国产1区2区| 亚洲天堂av电影| 亚洲激情久久久| 成人综合网网址| 欧美在线视频a| 欧美日韩国产丝袜美女| 欧美精品久久久久久久免费观看| 国产丝袜精品视频| 精品中文视频在线| 国产视频久久网| 国产在线播放91| 日韩在线中文字| 久久91精品国产91久久跳| 色在人av网站天堂精品| 一区二区日韩精品| 一区二区欧美久久| 色哟哟网站入口亚洲精品| 久久影院模特热| 毛片精品免费在线观看| 黑人巨大精品欧美一区二区一视频| 国模精品系列视频| 亚洲热线99精品视频| 久久综合久久美利坚合众国| 粗暴蹂躏中文一区二区三区| 日本欧美一二三区| 日韩成人av网址| 日本午夜精品理论片a级appf发布| 国产精品国产自产拍高清av水多| 丝袜美腿精品国产二区| 国产日韩欧美中文在线播放| 欧美性猛交视频| 亚洲精美色品网站| 国产精品永久免费视频| 51精品在线观看| 精品国产乱码久久久久久天美| 亚洲人成电影网站色…|