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

首頁(yè) > 數(shù)據(jù)庫(kù) > PostgreSQL > 正文

Mybatis調(diào)用PostgreSQL存儲(chǔ)過(guò)程實(shí)現(xiàn)數(shù)組入?yún)鬟f

2020-03-12 23:52:29
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

前言

項(xiàng)目中用到了Mybatis調(diào)用PostgreSQL存儲(chǔ)過(guò)程(自定義函數(shù))相關(guān)操作,由于PostgreSQL自帶數(shù)組類(lèi)型,所以有一個(gè)自定義函數(shù)的入?yún)⒕褪且粋€(gè)int數(shù)組,形如:

 

復(fù)制代碼 代碼如下:
CREATE OR REPLACE FUNCTION "public"."func_arr_update"(ids _int4)...

如上所示,參數(shù)是一個(gè)int數(shù)組,Mybatis提供了對(duì)調(diào)用存儲(chǔ)過(guò)程的支持,那么PostgreSQL獨(dú)有的數(shù)組類(lèi)型作為存儲(chǔ)過(guò)程的參數(shù)又將如何處理呢?其實(shí)很簡(jiǎn)單,mybatis提供了typeHandlers可以創(chuàng)建一個(gè)數(shù)組類(lèi)型的類(lèi)型處理器,具體做法為:實(shí)現(xiàn) org.apache.ibatis.type.TypeHandler 接口, 或繼承一個(gè)很便利的類(lèi) org.apache.ibatis.type.BaseTypeHandler, 然后可以選擇性地將它映射到一個(gè) JDBC 類(lèi)型,先稍作了解,后面再做詳細(xì)說(shuō)明,接下來(lái)依舊結(jié)合一個(gè)示例來(lái)看看。

 

創(chuàng)建自定義函數(shù)

如圖,第一步首先是創(chuàng)建一個(gè)用于調(diào)用的自定義函數(shù),功能也很簡(jiǎn)單,遍歷參數(shù)數(shù)組的每一個(gè)元素和t_student表的stuid做比較,若一致,則修改那條記錄的stuname(在其后拼接一段字符串),該自定義函數(shù)的DLL語(yǔ)句如下:

CREATE OR REPLACE FUNCTION "public"."func_arr_update"(ids _int4) RETURNS "pg_catalog"."void" AS $BODY$DECLARE   scount INTEGER;   rownum integer := 1;BEGIN    scount:=array_length(ids,1);    while rownum <= scount LOOP      update t_student set stuname = stuname || ' has been modified. ' where stuid = ids[rownum];      rownum := rownum + 1;  END LOOP;  RETURN;END$BODY$ LANGUAGE 'plpgsql' VOLATILE COST 100;ALTER FUNCTION "public"."func_arr_update"(ids _int4) OWNER TO "postgres";

很簡(jiǎn)單,獲取到參數(shù)數(shù)組的長(zhǎng)度后開(kāi)始循環(huán),匹配stuid并更新stuname,直接在數(shù)據(jù)庫(kù)調(diào)用一下看看結(jié)果:

Mybatis,PostgreSQL,數(shù)組

如上圖,可以看到成功修改了stuid為101,102和103的stuname,自定義函數(shù)已經(jīng)沒(méi)問(wèn)題了,接下來(lái)就具體看一下如何通過(guò)mybatis調(diào)用。

調(diào)用自定義函數(shù)

mybatis中調(diào)用自定義函數(shù)很簡(jiǎn)單,Mapper XML文件中的select元素直接提供了屬性支持——statementType,在官方文檔中可以看到:

Mybatis,PostgreSQL,數(shù)組

如上圖,statementType的值默認(rèn)是PREPARED,也就是說(shuō)底層默認(rèn)會(huì)使用jdbc的PreparedStatement,而我們都知道jdbc調(diào)用存儲(chǔ)過(guò)程時(shí)需要用CallableStatement,所以在這里我們需要將statementType的值設(shè)置為CALLABLE。

mybatis默認(rèn)的ArrayTypeHandler

調(diào)用存儲(chǔ)過(guò)程很簡(jiǎn)單,那么接下來(lái)的問(wèn)題是如何在mybatis中傳一個(gè)數(shù)組參數(shù)到存儲(chǔ)過(guò)程中呢?這里就要用到另外一個(gè)概念——TypeHandler,這是mybatis提供的自定義類(lèi)型轉(zhuǎn)換器,mybatis在預(yù)編譯語(yǔ)句對(duì)象(PreparedStatement)設(shè)置參數(shù)時(shí)或是從結(jié)果集中取值時(shí)都會(huì)用類(lèi)型處理器將獲取的值以合適的方式轉(zhuǎn)換成Java類(lèi)型,mybatis默認(rèn)實(shí)現(xiàn)了一部分TypeHandler供我們使用,當(dāng)我們沒(méi)有指定TypeHandler時(shí)(大多數(shù)情況都不會(huì)指定),mybatis會(huì)根據(jù)參數(shù)或者返回結(jié)果的不同,默認(rèn)為我們選擇合適的TypeHandler處理,下面可以通過(guò)查看源碼大概看一下默認(rèn)的TypeHandler,導(dǎo)入源碼后可以在org.apache.ibatis.type包下找到一個(gè)TypeHandlerRegistry類(lèi),typeHandler正是通過(guò)這個(gè)類(lèi)管理的,先看一下它的構(gòu)造方法:

 

 public TypeHandlerRegistry() {  register(Boolean.class, new BooleanTypeHandler());  register(boolean.class, new BooleanTypeHandler());  register(JdbcType.BOOLEAN, new BooleanTypeHandler());  register(JdbcType.BIT, new BooleanTypeHandler());  register(Byte.class, new ByteTypeHandler());  register(byte.class, new ByteTypeHandler());  register(JdbcType.TINYINT, new ByteTypeHandler());  register(Short.class, new ShortTypeHandler());  register(short.class, new ShortTypeHandler());  register(JdbcType.SMALLINT, new ShortTypeHandler());  register(Integer.class, new IntegerTypeHandler());  register(int.class, new IntegerTypeHandler());  register(JdbcType.INTEGER, new IntegerTypeHandler());  register(Long.class, new LongTypeHandler());  register(long.class, new LongTypeHandler());  register(Float.class, new FloatTypeHandler());  register(float.class, new FloatTypeHandler());  register(JdbcType.FLOAT, new FloatTypeHandler());  register(Double.class, new DoubleTypeHandler());  register(double.class, new DoubleTypeHandler());  register(JdbcType.DOUBLE, new DoubleTypeHandler());  register(String.class, new StringTypeHandler());  register(String.class, JdbcType.CHAR, new StringTypeHandler());  register(String.class, JdbcType.CLOB, new ClobTypeHandler());  register(String.class, JdbcType.VARCHAR, new StringTypeHandler());  register(String.class, JdbcType.LONGVARCHAR, new ClobTypeHandler());  register(String.class, JdbcType.NVARCHAR, new NStringTypeHandler());  register(String.class, JdbcType.NCHAR, new NStringTypeHandler());  register(String.class, JdbcType.NCLOB, new NClobTypeHandler());  register(JdbcType.CHAR, new StringTypeHandler());  register(JdbcType.VARCHAR, new StringTypeHandler());  register(JdbcType.CLOB, new ClobTypeHandler());  register(JdbcType.LONGVARCHAR, new ClobTypeHandler());  register(JdbcType.NVARCHAR, new NStringTypeHandler());  register(JdbcType.NCHAR, new NStringTypeHandler());  register(JdbcType.NCLOB, new NClobTypeHandler());  register(Object.class, JdbcType.ARRAY, new ArrayTypeHandler());  register(JdbcType.ARRAY, new ArrayTypeHandler());  register(BigInteger.class, new BigIntegerTypeHandler());  register(JdbcType.BIGINT, new LongTypeHandler());  register(BigDecimal.class, new BigDecimalTypeHandler());  register(JdbcType.REAL, new BigDecimalTypeHandler());  register(JdbcType.DECIMAL, new BigDecimalTypeHandler());  register(JdbcType.NUMERIC, new BigDecimalTypeHandler());  register(Byte[].class, new ByteObjectArrayTypeHandler());  register(Byte[].class, JdbcType.BLOB, new BlobByteObjectArrayTypeHandler());  register(Byte[].class, JdbcType.LONGVARBINARY, new BlobByteObjectArrayTypeHandler());  register(byte[].class, new ByteArrayTypeHandler());  register(byte[].class, JdbcType.BLOB, new BlobTypeHandler());  register(byte[].class, JdbcType.LONGVARBINARY, new BlobTypeHandler());  register(JdbcType.LONGVARBINARY, new BlobTypeHandler());  register(JdbcType.BLOB, new BlobTypeHandler());  register(Object.class, UNKNOWN_TYPE_HANDLER);  register(Object.class, JdbcType.OTHER, UNKNOWN_TYPE_HANDLER);  register(JdbcType.OTHER, UNKNOWN_TYPE_HANDLER);  register(Date.class, new DateTypeHandler());  register(Date.class, JdbcType.DATE, new DateOnlyTypeHandler());  register(Date.class, JdbcType.TIME, new TimeOnlyTypeHandler());  register(JdbcType.TIMESTAMP, new DateTypeHandler());  register(JdbcType.DATE, new DateOnlyTypeHandler());  register(JdbcType.TIME, new TimeOnlyTypeHandler());  register(java.sql.Date.class, new SqlDateTypeHandler());  register(java.sql.Time.class, new SqlTimeTypeHandler());  register(java.sql.Timestamp.class, new SqlTimestampTypeHandler());  // issue #273  register(Character.class, new CharacterTypeHandler());  register(char.class, new CharacterTypeHandler()); }

如上所示,這就是全部默認(rèn)的typeHandler了,注意一下46,47行可以看到默認(rèn)有一個(gè)ArrayTypeHandler,順便看一下它的源碼:

 

/* *  Copyright 2009-2012 The MyBatis Team * *  Licensed under the Apache License, Version 2.0 (the "License"); *  you may not use this file except in compliance with the License. *  You may obtain a copy of the License at * *    http://www.apache.org/licenses/LICENSE-2.0 * *  Unless required by applicable law or agreed to in writing, software *  distributed under the License is distributed on an "AS IS" BASIS, *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *  See the License for the specific language governing permissions and *  limitations under the License. */package org.apache.ibatis.type;import java.sql.Array;import java.sql.CallableStatement;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;public class ArrayTypeHandler extends BaseTypeHandler<Object> { public ArrayTypeHandler() {  super(); } @Override public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {  ps.setArray(i, (Array) parameter); } @Override public Object getNullableResult(ResultSet rs, String columnName) throws SQLException {  Array array = rs.getArray(columnName);  return array == null ? null : array.getArray(); } @Override public Object getNullableResult(ResultSet rs, int columnIndex) throws SQLException {  Array array = rs.getArray(columnIndex);  return array == null ? null : array.getArray(); } @Override public Object getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {  Array array = cs.getArray(columnIndex);  return array == null ? null : array.getArray(); }}

那它能否識(shí)別PostgreSQL的數(shù)組類(lèi)型并將它自動(dòng)轉(zhuǎn)換成Java數(shù)組類(lèi)型呢?按官方的說(shuō)法,既然這是默認(rèn)的typeHandler,那么我們無(wú)需做任何配置mybatis會(huì)自動(dòng)嘗試適配,所以直接寫(xiě)測(cè)試代碼看看:

@Testpublic void testFunc1() {  SqlSession session = sqlSessionFactory.openSession();  try {    Map<String, Object> map = new HashMap<String, Object>();    map.put("ids", new Integer[] { 101, 102, 103 });    session.update("com.wl.entity.StudentMapper.testFuncUpdate2", map);    session.commit();  } catch (Exception e) {    e.printStackTrace();  } finally {    session.close();  }}
<update id="testFuncUpdate2" statementType="CALLABLE">  {call func_arr_update (#{ids,mode=IN})} </update>

如上所示,參數(shù)傳的是一個(gè)Integer[],直接運(yùn)行一下junit看看測(cè)試結(jié)果:

Mybatis,PostgreSQL,數(shù)組

Can't infer the SQL type to use for an instance of [Ljava.lang.Integer;. Use setObject() with an explicit Types value to specify the type to use.

異常log如上所示,在調(diào)用AbstractJdbc2Statement類(lèi)的setObject方法時(shí)拋出異常,那么再看看這個(gè)方法的源碼:

  /*   * This stores an Object into a parameter.   */  public void setObject(int parameterIndex, Object x) throws SQLException  {    checkClosed();    if (x == null)      setNull(parameterIndex, Types.OTHER);    else if (x instanceof String)      setString(parameterIndex, (String)x);    else if (x instanceof BigDecimal)      setBigDecimal(parameterIndex, (BigDecimal)x);    else if (x instanceof Short)      setShort(parameterIndex, ((Short)x).shortValue());    else if (x instanceof Integer)      setInt(parameterIndex, ((Integer)x).intValue());    else if (x instanceof Long)      setLong(parameterIndex, ((Long)x).longValue());    else if (x instanceof Float)      setFloat(parameterIndex, ((Float)x).floatValue());    else if (x instanceof Double)      setDouble(parameterIndex, ((Double)x).doubleValue());    else if (x instanceof byte[])      setBytes(parameterIndex, (byte[])x);    else if (x instanceof java.sql.Date)      setDate(parameterIndex, (java.sql.Date)x);    else if (x instanceof Time)      setTime(parameterIndex, (Time)x);    else if (x instanceof Timestamp)      setTimestamp(parameterIndex, (Timestamp)x);    else if (x instanceof Boolean)      setBoolean(parameterIndex, ((Boolean)x).booleanValue());    else if (x instanceof Byte)      setByte(parameterIndex, ((Byte)x).byteValue());    else if (x instanceof Blob)      setBlob(parameterIndex, (Blob)x);    else if (x instanceof Clob)      setClob(parameterIndex, (Clob)x);    else if (x instanceof Array)      setArray(parameterIndex, (Array)x);    else if (x instanceof PGobject)      setPGobject(parameterIndex, (PGobject)x);    else if (x instanceof Character)      setString(parameterIndex, ((Character)x).toString());    else if (x instanceof Map)      setMap(parameterIndex, (Map)x);    else    {      // Can't infer a type.      throw new PSQLException(GT.tr("Can''t infer the SQL type to use for an instance of {0}. Use setObject() with an explicit Types value to specify the type to use.", x.getClass().getName()), PSQLState.INVALID_PARAMETER_TYPE);    }  }

我們參數(shù)傳進(jìn)去的Integer[]數(shù)組是一個(gè)Object數(shù)組,而 setObject(int parameterIndex, Object x)方法的第二個(gè)參數(shù)是Object,所以這里這里自然無(wú)法匹配也就報(bào)錯(cuò)了,那么換成int[]可以嗎?在上面的else if語(yǔ)句中明顯沒(méi)有x instanceof int[]這行代碼,所以當(dāng)然也不行,說(shuō)到這里也就明確了mybatis默認(rèn)提供的ArrayTypeHandler是無(wú)法自動(dòng)識(shí)別PostgreSQL的數(shù)組類(lèi)型,我們必須自定義一個(gè)參數(shù)為Object[]的ArrayTypeHandler才能實(shí)現(xiàn)匹配。

自定義ArrayTypeHandler

如題,先貼上代碼:

 

package com.wl.util;import java.sql.Array;import java.sql.CallableStatement;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import org.apache.ibatis.type.BaseTypeHandler;import org.apache.ibatis.type.JdbcType;import org.apache.ibatis.type.MappedJdbcTypes;import org.apache.ibatis.type.TypeException;@MappedJdbcTypes(JdbcType.ARRAY)public class ArrayTypeHandler extends BaseTypeHandler<Object[]> {  private static final String TYPE_NAME_VARCHAR = "varchar";  private static final String TYPE_NAME_INTEGER = "integer";  private static final String TYPE_NAME_BOOLEAN = "boolean";  private static final String TYPE_NAME_NUMERIC = "numeric";  @Override  public void setNonNullParameter(PreparedStatement ps, int i,      Object[] parameter, JdbcType jdbcType) throws SQLException {    String typeName = null;    if (parameter instanceof Integer[]) {      typeName = TYPE_NAME_INTEGER;    } else if (parameter instanceof String[]) {      typeName = TYPE_NAME_VARCHAR;    } else if (parameter instanceof Boolean[]) {      typeName = TYPE_NAME_BOOLEAN;    } else if (parameter instanceof Double[]) {      typeName = TYPE_NAME_NUMERIC;    }    if (typeName == null) {      throw new TypeException(          "ArrayTypeHandler parameter typeName error, your type is "              + parameter.getClass().getName());    }    Connection conn = ps.getConnection();    Array array = conn.createArrayOf(typeName, parameter);    ps.setArray(i, array);  }  @Override  public Object[] getNullableResult(ResultSet rs, String columnName)      throws SQLException {    return getArray(rs.getArray(columnName));  }  @Override  public Object[] getNullableResult(ResultSet rs, int columnIndex)      throws SQLException {    return getArray(rs.getArray(columnIndex));  }  @Override  public Object[] getNullableResult(CallableStatement cs, int columnIndex)      throws SQLException {    return getArray(cs.getArray(columnIndex));  }  private Object[] getArray(Array array) {    if (array == null) {      return null;    }    try {      return (Object[]) array.getArray();    } catch (Exception e) {    }    return null;  }}

如上所示,我們指定了參數(shù)類(lèi)型為Object[],這樣就可以接收Integer[]類(lèi)型的參數(shù)了,關(guān)鍵是44~46行,postgresql的驅(qū)動(dòng)類(lèi)AbstractJdbc4Connection實(shí)現(xiàn)了Connect接口的createArrayOf方法,源碼如下:

  public Array createArrayOf(String typeName, Object[] elements) throws SQLException  {    checkClosed();    int oid = getTypeInfo().getPGArrayType(typeName);    if (oid == Oid.UNSPECIFIED)      throw new PSQLException(GT.tr("Unable to find server array type for provided name {0}.", typeName), PSQLState.INVALID_NAME);    char delim = getTypeInfo().getArrayDelimiter(oid);    StringBuffer sb = new StringBuffer();    appendArray(sb, elements, delim);    // This will not work once we have a JDBC 5,    // but it'll do for now.    return new Jdbc4Array(this, oid, sb.toString());  }

這樣通過(guò)自定義的ArrayTypeHandler就可以在Mybatis中方便的操作數(shù)組類(lèi)型數(shù)據(jù)了,最后再測(cè)試一下,測(cè)試類(lèi)代碼不變,僅需在調(diào)用存儲(chǔ)過(guò)程時(shí)指定mapper文件的typeHandler即可:

@Testpublic void testFunc1() {  SqlSession session = sqlSessionFactory.openSession();  try {    Map<String, Object> map = new HashMap<String, Object>();    map.put("ids", new Integer[] { 101, 102, 103 });    session.update("com.wl.entity.StudentMapper.testFuncUpdate2", map);    session.commit();  } catch (Exception e) {    e.printStackTrace();  } finally {    session.close();  }}
<update id="testFuncUpdate2" statementType="CALLABLE">  {call func_arr_update (#{ids,mode=IN,typeHandler=com.wl.util.ArrayTypeHandler})} </update>

再次運(yùn)行junit看一下測(cè)試結(jié)果:

Mybatis,PostgreSQL,數(shù)組

如上所示,此時(shí)已經(jīng)可以成功調(diào)用參數(shù)為Integer[]數(shù)組的pg自定義函數(shù)了。

總結(jié)

簡(jiǎn)單記錄一下在mybatis中調(diào)用postgresql自定義函數(shù)時(shí)傳遞數(shù)組參數(shù)的解決方案,希望對(duì)遇到同樣問(wèn)題的朋友有所幫助,The End。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持VEVB武林網(wǎng)。


注:相關(guān)教程知識(shí)閱讀請(qǐng)移步到PostgreSQL頻道。
發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
国产色综合一区| 91手机视频在线| 性感美女久久精品| 日韩在线伦理| 中文字幕在线观看免费视频| 亚洲欧美日韩中文字幕一区二区三区| 亚洲色婷婷综合开心网| 91 com成人网| 97欧美成人| 亚洲精品国产拍免费91在线| 成人免费看片网站| 国内精品久久久久久中文字幕| 欧美国产成人精品一区二区三区| 日本在线视频www鲁啊鲁| 国产香蕉视频在线看| 青青青免费视频观看在线| 日韩在线观看免费| 欧美午夜性视频| 亚洲精品国产精品乱码不卡| 精品一区二区国语对白| 精品亚洲成人| 亚洲国产精品美女| 欧美视频精品在线观看| 欧美精品成人91久久久久久久| 国产手机av在线| 日韩一区二区视频在线观看| 涩涩网站在线看| 一二三区视频在线观看| 色妞欧美日韩在线| 精品视频全国免费看| 黄色网在线视频| 欧美xx在线| 成人久久久久久久| 午夜不卡av免费| 成人精品一二三区| 99国产精品久久久久久| y4480在线8影院| 国产区二精品视| 精品无人区一区二区三区| 国产精品久久久久久久久免费丝袜| 99电影在线观看| 亚洲视频一区二区在线| 国产91av在线播放| 舐め犯し波多野结衣在线观看| 久久人人爽人人爽人人片av不| 亚洲欧美综合一区| 香蕉521av成人网| 日本不卡一区| 亚洲精品乱码久久久久久久久久久久| 日本一区二区三区电影免费观看| 国产成人欧美在线观看| 四虎永久在线精品无码视频| 色婷婷狠狠18禁久久| 一区二区亚洲欧洲国产日韩| 同心难改在线观看| 天堂在线一二区| 欧美一级本道电影免费专区| 浮力国产第一页| 另类欧美小说| 中文字幕不卡免费视频| 国产精品久久久久久久久久新婚| 清纯唯美日韩| 久久久久中文字幕2018| 中文在线最新版天堂| 日批视频在线看| 欧美久久久网站| 五十路中文字幕| 亚洲va久久久噜噜噜久久天堂| 黄色污网站在线观看| 91麻豆精品在线| 亚洲精品国产一区二区三区| 黄漫在线观看| 成a人片在线观看www视频| 夫妻av一区二区| 久久久久无码国产精品一区| 四虎免费视频| 51精品在线| eeuss国产一区二区三区四区| av电影中文字幕| www.狠狠色.com| 手机看片日韩av| av日韩在线播放| 男女一区二区三区免费| 黄色激情视频在线观看| 99精品视频中文字幕| 国产真实乱对白精彩久久| 一区二区三区久久久久| 国产精品毛片a∨一区二区三区|国| 国产裸体美女永久免费无遮挡| 久久精品一区四区| 国产剧情一区二区三区| 精品夜夜澡人妻无码av| 范冰冰一级做a爰片久久毛片| 亚洲中文字幕在线一区| 日韩毛片在线| 2019亚洲日韩新视频| 最新在线观看av| 欧美老女人xx| 欧美夫妻性生活视频| 最近2019年中文视频免费在线观看| 大尺度做爰床戏呻吟舒畅| 日韩经典一区二区三区| 国产福利91精品| 国产精品一区二区在线观看网站| 午夜欧美一区二区三区免费观看| 色94色欧美一区| 亚洲国产欧美一区二区三区不卡| 午夜影院观看视频免费| 91丨porny丨户外露出| 欧美超碰在线| 四虎永久在线精品| 国产又粗又长又黄的视频| 麻豆蜜桃在线观看| 亚洲黄色免费电影| 一区二区三区四区久久| 久久久一本精品99久久精品| 在线欧美不卡| 日本免费一区视频| 2020中文字字幕在线不卡| 伊人激情综合网| theav精尽人亡av| 国产精品久久婷婷| 国产精品入口麻豆免费看| 91大片在线观看| 性色av一区二区三区| 欧美一区二区三区播放| 日韩精品免费观看视频| 久久亚洲成人| 好吊色在线视频| 91xxx视频| 亚洲欧美综合区自拍另类| 亚洲一级片在线观看| 国产日韩av在线播放| 国产精品一级在线| 国产三级在线| 精品理论电影在线| 日韩免费福利电影在线观看| 97久久国产亚洲精品超碰热| 欧美在线视频在线播放完整版免费观看| 精品日本一线二线三线不卡| 国产精品福利久久久| 成人av影院在线观看| 久久久久免费看黄a片app| 99久久99久久精品国产| 亚洲柠檬福利资源导航| 日本黄区免费视频观看| 97免费观看视频| 国产成人av一区二区三区在线观看| 91精品国产毛片武则天| 免费做暖暖免费观看日本| 中文字幕日韩亚洲| 亚洲午夜影视影院在线观看| 性色av一区二区三区在线观看| 卡一卡二卡三在线观看| 欧美黑人又粗大| 亚洲一区二区三区在线观看视频| 国产欧美日韩免费看aⅴ视频| 国产精品拍拍拍| 日本伊人精品一区二区三区介绍| 日本91av在线播放| 亚洲午夜小视频| 欧美偷拍综合| 久久久久北条麻妃免费看| www.5588.com毛片| 国产精品素人一区二区| jizz在线观看| 免费成人深夜夜行p站| 91成人在线播放| 国产不卡视频在线观看| 免费女人黄页| 亚洲视频一二区| 亚洲AV第二区国产精品| 久久精品99国产精| 成人精品3d动漫| 亚洲综合无码一区二区| 手机免费观看av| 国产永久av在线| 在线免费观看污视频| 丁香花在线影院| 这里只有精品9| 成人免费看黄网址| 中文字幕在线播放一区| 1024av视频| 国产不卡在线一区| 日本一区福利在线| 亚洲性线免费观看视频成熟| 全国男人的天堂天堂网| 有没有片在线看www| 午夜老司机在线观看| 婷婷综合成人| 国产综合18久久久久久| 91精品国产自产在线丝袜啪| 成人精品亚洲| 欧美亚洲禁片免费| 成人av在线资源网| 亚洲伊人一本大道中文字幕| av日韩中文字幕| 日韩av免费在线播放| 激情视频综合网| 国产激情精品久久久第一区二区| 日本女优一区| 日本黄色入口| 中文字幕无码日韩专区免费| bt在线麻豆视频| 黄色片在线观看网站| 免费福利在线视频| 色网在线视频| 日本高清久久一区二区三区| 日本福利视频在线| 国产精品日韩一区| 亚洲av人人澡人人爽人人夜夜| 国产亚洲精品久久久久久移动网络| 欧美日韩国产999| 一区二区三区四区欧美| 精品久久久久久久久国产字幕| 久久精品夜色噜噜亚洲aⅴ| 国产精品一区二区黑人巨大| 色一情一乱一乱一区91| 伊人久久综合一区二区| 欧美sm一区| 成人免费视频免费观看| 日本福利午夜视频在线| 久久久久久成人精品| 国产成人在线视频观看| 无人视频在线观看免费| 亚洲欧洲99久久| 久久久久久久久久国产精品| 国产成人无码精品久久久久| 日韩人妻无码精品久久久不卡| 久久久高清一区二区三区| 久久婷婷国产91天堂综合精品| 日本美女久久久| 91免费精品国偷自产在线| av资源在线| 日本中文字幕在线看| 99精品欧美一区二区| 亚洲超碰在线| 国产精品亚洲一区二区无码| 激情文学一区| 三级全黄做爰视频| 美女被久久久| 色综合久久五月天| 黑人操日本美女| 日韩一区二区三区国产| 精品久久久久久久久久久下田| 亚欧洲精品在线视频| 亚洲中文字幕久久精品无码喷水| 俺去啦在线观看| 国产v综合ⅴ日韩v欧美大片| 国产欧美日韩免费| 久久亚洲综合国产精品99麻豆精品福利| 欧美激情第6页| 欧美成人免费视频| 羞羞视频网站| 真人bbbbbbbbb毛片| 国产午夜精品一区二区三区嫩草| 日本女人黄色片| 日本不卡在线观看视频| 91九色蝌蚪在线| 婷婷无套内射影院| 18视频在线观看娇喘| 丝瓜av网站精品一区二区| 影音先锋男人资源站在线观看| 欧美性受xxxx黑人爽| 国产一起色一起爱| 国产精品超碰| 亚洲精品久久久久久宅男| 日韩免费不卡视频| 91在线无精精品白丝| 色老头一区二区三区| 黄页网站免费在线观看| 美女网站色91| 无码国产69精品久久久久网站| 性chinese极品按摩| 丰满少妇乱子伦精品看片| 亚洲国产精品人久久电影| av小次郎收藏| 人人妻人人澡人人爽人人精品| 狠狠综合久久av一区二区老牛| 青草视频在线观看视频| 免费毛片在线看片免费丝瓜视频| 中国老太性bbbxxxx| 国产交换配乱淫视频免费| 久久久久网址| 天天干夜夜操| 欧美一区二区三区四区在线观看| 国产美女视频黄a视频免费| 爱爱视频网站免费| 国产成人在线一区| 亚洲精品影片| 成年人免费网站| 国产三级视频在线播放| 亚洲久久在线观看| 美女脱光内衣内裤| 一区二区视频网| 欧美一区二区国产| 先锋影视中文字幕| 68精品久久久久久欧美| 粉嫩精品导航导航| 免费人成黄页网站在线一区二区| 亚洲成人第一网站| 六月丁香久久丫| 国产大片中文字幕在线观看| 一个人免费观看日本www视频| 九色porny自拍| 91av在线免费观看视频| 日韩va亚洲va欧美va清高| 在线观看黄av| dy888夜精品国产专区| 精品国产av色一区二区深夜久久| 亚洲精品永久视频| 久久国际精品| 国产精品伦理一区二区三区| 国产精品一区二区中文字幕| 午夜福制92视频| 中文字幕网站在线观看| 亚洲精华液一区二区三区| 亚洲免费看片| 精品亚洲欧美日韩| 精品日韩电影| 一二三区免费视频| 啊v视频在线一区二区三区| 亚洲视频在线免费观看| 国产精品免费精品一区| 无码精品一区二区三区在线播放| 无码任你躁久久久久久老妇| 九九精品视频在线看| 七七成人影院|