午夜视频免费看_日韩三级电影网站_国产精品久久一级_亚洲一级在线播放_人妻体内射精一区二区三区_91夜夜揉人人捏人人添红杏_91福利在线导航_国产又粗又猛又黄又爽无遮挡_欧美日韩一区在线播放_中文字幕一区二区三区四区不卡 _日日夜夜精品视频免费观看_欧美韩日一区二区三区

主頁 > 知識庫 > Mybatis調用PostgreSQL存儲過程實現數組入參傳遞

Mybatis調用PostgreSQL存儲過程實現數組入參傳遞

熱門標簽:辦公外呼電話系統 重慶自動外呼系統定制 外呼調研系統 打電話智能電銷機器人授權 合肥公司外呼系統運營商 地圖標注和圖片名稱的區別 美容工作室地圖標注 海豐有多少商家沒有地圖標注 漯河外呼電話系統

前言

項目中用到了Mybatis調用PostgreSQL存儲過程(自定義函數)相關操作,由于PostgreSQL自帶數組類型,所以有一個自定義函數的入參就是一個int數組,形如:

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

如上所示,參數是一個int數組,Mybatis提供了對調用存儲過程的支持,那么PostgreSQL獨有的數組類型作為存儲過程的參數又將如何處理呢?其實很簡單,mybatis提供了typeHandlers可以創建一個數組類型的類型處理器,具體做法為:實現 org.apache.ibatis.type.TypeHandler 接口, 或繼承一個很便利的類 org.apache.ibatis.type.BaseTypeHandler, 然后可以選擇性地將它映射到一個 JDBC 類型,先稍作了解,后面再做詳細說明,接下來依舊結合一個示例來看看。

創建自定義函數

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

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

很簡單,獲取到參數數組的長度后開始循環,匹配stuid并更新stuname,直接在數據庫調用一下看看結果:

如上圖,可以看到成功修改了stuid為101,102和103的stuname,自定義函數已經沒問題了,接下來就具體看一下如何通過mybatis調用。

調用自定義函數

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

如上圖,statementType的值默認是PREPARED,也就是說底層默認會使用jdbc的PreparedStatement,而我們都知道jdbc調用存儲過程時需要用CallableStatement,所以在這里我們需要將statementType的值設置為CALLABLE。

mybatis默認的ArrayTypeHandler

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

 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());
 }

如上所示,這就是全部默認的typeHandler了,注意一下46,47行可以看到默認有一個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 BaseTypeHandlerObject> {

 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();
 }

}

那它能否識別PostgreSQL的數組類型并將它自動轉換成Java數組類型呢?按官方的說法,既然這是默認的typeHandler,那么我們無需做任何配置mybatis會自動嘗試適配,所以直接寫測試代碼看看:

@Test
public void testFunc1() {
  SqlSession session = sqlSessionFactory.openSession();
  try {
    MapString, Object> map = new HashMapString, 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>

如上所示,參數傳的是一個Integer[],直接運行一下junit看看測試結果:

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如上所示,在調用AbstractJdbc2Statement類的setObject方法時拋出異常,那么再看看這個方法的源碼:

  /*
   * 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);
    }
  }

我們參數傳進去的Integer[]數組是一個Object數組,而 setObject(int parameterIndex, Object x)方法的第二個參數是Object,所以這里這里自然無法匹配也就報錯了,那么換成int[]可以嗎?在上面的else if語句中明顯沒有x instanceof int[]這行代碼,所以當然也不行,說到這里也就明確了mybatis默認提供的ArrayTypeHandler是無法自動識別PostgreSQL的數組類型,我們必須自定義一個參數為Object[]的ArrayTypeHandler才能實現匹配。

自定義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 BaseTypeHandlerObject[]> {

  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;
  }
}

如上所示,我們指定了參數類型為Object[],這樣就可以接收Integer[]類型的參數了,關鍵是44~46行,postgresql的驅動類AbstractJdbc4Connection實現了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());
  }

這樣通過自定義的ArrayTypeHandler就可以在Mybatis中方便的操作數組類型數據了,最后再測試一下,測試類代碼不變,僅需在調用存儲過程時指定mapper文件的typeHandler即可:

@Test
public void testFunc1() {
  SqlSession session = sqlSessionFactory.openSession();
  try {
    MapString, Object> map = new HashMapString, 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>

再次運行junit看一下測試結果:

如上所示,此時已經可以成功調用參數為Integer[]數組的pg自定義函數了。

總結

簡單記錄一下在mybatis中調用postgresql自定義函數時傳遞數組參數的解決方案,希望對遇到同樣問題的朋友有所幫助,The End。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

您可能感興趣的文章:
  • MyBatis傳入參數為List對象的實現
  • mybatis條件語句中帶數組參數的處理
  • MyBatis傳入數組集合類并使用foreach遍歷
  • 基于mybatis中數組傳遞注意事項

標簽:衡陽 來賓 錦州 蚌埠 株洲 烏海 晉城 珠海

巨人網絡通訊聲明:本文標題《Mybatis調用PostgreSQL存儲過程實現數組入參傳遞》,本文關鍵詞  Mybatis,調用,PostgreSQL,存儲,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《Mybatis調用PostgreSQL存儲過程實現數組入參傳遞》相關的同類信息!
  • 本頁收集關于Mybatis調用PostgreSQL存儲過程實現數組入參傳遞的相關信息資訊供網民參考!
  • 推薦文章
    中文字幕在线综合| 亚洲国产精品久久艾草纯爱| www.久久久久| 中国一级特黄毛片| 国产成人精品久久| 成人动漫av在线| 日韩肉感妇bbwbbwbbw| 国产一区二区三区视频| 石原莉奈一区二区三区在线观看 | 亚洲精品高清在线观看| av网站大全免费| 北岛玲一区二区| 欧美日韩国产综合草草| 国产一二三四在线视频| 欧美日韩国产一区在线| 欧美亚洲丝袜传媒另类| 久久精品夜夜夜夜夜久久| 色中色一区二区| 日韩国产高清一区| 精品国产一区二区三区四| 黄色成人av在线| 精品国产日本| 这里只有久久精品视频| 欧美精品自拍偷拍动漫精品| 艳色歌舞团一区二区三区| 国产欧美日韩综合精品一区二区三区| 欧美日韩午夜在线| 久久99久久精品欧美| 欧美性jizz18性欧美| 不卡视频一区二区三区| 免费在线一区二区三区| 性欧美大战久久久久久久久| 精品国产乱码久久久久| 一级黄色片免费看| 亚洲视频在线观看视频| 亚洲精品久久久久久| 欧美羞羞免费网站| 久久久久久久久毛片| 亚洲国产激情一区二区三区| 日韩一二三四区| 国产一区二区视频在线| 亚洲一级Av无码毛片久久精品| 国产va免费精品高清在线| 国产精品一区2区| 亚洲国产欧美日韩| 国产精品久久久久久久久果冻传媒 | 久久夜色精品国产噜噜av | av成人老司机| 久久精品女同亚洲女同13| 色婷婷久久久久swag精品| 成人免费无遮挡无码黄漫视频| 欧美成人精品影院| 永久免费毛片在线观看| 日韩av片永久免费网站| 亚洲欧美一区二区三区四区五区| 日本高清不卡在线观看| 国产精品又粗又长| 久久综合999| 视频在线精品一区| a级精品国产片在线观看| 懂色中文一区二区三区在线视频| 亚洲第一免费视频| 欧美一级在线亚洲天堂| 黄瓜视频在线免费观看| 久久99热精品| 西西44rtwww国产精品| 国产一区二区av| 四虎影院中文字幕| 亚洲毛片在线免费观看| 日韩欧美激情视频| 亚洲美女av在线| 超碰手机在线观看| 亚洲欧美综合v| 欧美成人综合色| 久久久国产在线视频| 亚洲视频免费播放| 欧美大片va欧美在线播放| 国产一级特黄a高潮片| 日韩在线一区二区三区免费视频| 三级黄色在线观看| 日韩精品亚洲精品| 麻豆视频在线免费看| 亚洲一区www| 日本少妇裸体做爰| 精品国产一区久久久| 波多野结衣视频网址| 欧美黑人巨大精品一区二区| 一级视频在线播放| 国产精品直播网红| 久久久亚洲人| 免费在线成人av| 91在线视频网址| 国产免费观看高清视频| 午夜激情一区二区| 丰满人妻一区二区三区大胸| 欧美日韩一区二区三区视频| 日本高清www| 亚洲欧美综合精品久久成人| 国产特黄大片aaaa毛片| 欧美整片在线观看| 婷婷在线免费视频| 裸体丰满少妇做受久久99精品| 97国产精品videossex| 国产老熟妇精品观看| 日本韩国欧美三级| 美女久久久久久久久| 337p日本欧洲亚洲大胆精品| √天堂中文官网8在线| 欧美福利小视频| 亚洲 美腿 欧美 偷拍| 欧美日韩亚洲综合一区二区三区激情在线| 久久只精品国产| 手机看片福利盒子久久| 欧美一区二区三区视频在线观看| 国产精品变态另类虐交| 97在线视频免费观看| 久久青草久久| 视频一区二区视频| 欧美日韩免费区域视频在线观看| 99久久久久久久久久| 久久亚洲精品一区二区| 可以免费观看的毛片| 色99中文字幕| 欧美日韩国产专区| 国产一二三四区| 国产精品av在线| 高清成人在线观看| 日本999视频| 日韩激情在线视频| 成人av手机在线| 中文字幕在线亚洲精品| 欧美视频一区二区三区…| 91插插插插插插| 成人欧美一区二区三区黑人| 国产欧美一区二区三区网站| 国产九九九视频| 久久国产一区二区三区| 久久综合伊人| 黄色av免费在线播放| 亚洲视频在线观看免费| 天堂成人在线视频| 在线观看污视频| 欧美日韩视频在线观看一区二区三区| 日韩av在线电影| 国产自产在线视频一区| 一个色综合网站| 性一交一乱一伧老太| 国产亚洲精品91在线| 毛片基地黄久久久久久天堂| 国产午夜福利在线播放| 亚洲精品一区二区三区影院 | 大尺度一区二区| 精品国产免费久久久久久婷婷| 日韩专区在线播放| 免费的成人av| 午夜免费高清视频| 色偷偷av亚洲男人的天堂| 成人黄色在线网站| 中文字幕22页| 久久香蕉国产线看观看av| 美女网站色91| 激情综合网俺也去| 精品国产髙清在线看国产毛片| 国产叼嘿视频在线观看| 男女裸体影院高潮| 亚洲电影免费观看高清| 国产香蕉在线观看| 国产亚洲精品网站| 国产午夜精品一区二区三区| 天堂av一区二区三区| 国产成人a亚洲精v品无码| 亚洲精品国产品国语在线| 首页亚洲欧美制服丝腿| 日批视频在线免费看| 中文字幕日韩高清| 国产在线国偷精品产拍免费yy| 天堂一区在线观看| 久久久久中文字幕2018| 26uuu国产电影一区二区| 国产精品情侣呻吟对白视频| 国产精品www| 亚洲免费av高清| 国产精品第72页| 亚洲成人自拍视频| 日韩av在线网站| 久久99精品国产麻豆婷婷洗澡| 黄色永久免费网站| 91成人国产在线观看| 日本一区二区三区四区 | 中文字幕一区二区三区四区视频| 中文字幕黄色大片| 国产亚洲精品成人av久久ww| 国产乱一区二区| mm131丰满少妇人体欣赏图| 欧美专区在线播放| 精品国产精品自拍| 91成人国产综合久久精品| 国产av熟女一区二区三区| 亚洲毛片在线看| 波多野结衣精品在线| 国产人与禽zoz0性伦| 成人精品一二区| 欧美日韩国产欧美日美国产精品| 国精品人妻无码一区二区三区喝尿| 男女无套免费视频网站动漫| 97精品一区二区视频在线观看| 国产精品天美传媒沈樵| 日韩av在线电影| 噜噜噜久久亚洲精品国产品麻豆| 欧美xxxx综合视频| 亚洲精品乱码久久久久久| 日韩免费av网站| 天天干天天操天天做| 久草精品电影| 中文字幕日韩精品在线| 精品久久香蕉国产线看观看gif| 国产成人av自拍| 欧美精品色哟哟| 亚洲 中文字幕 日韩 无码| 热re99久久精品国产99热| 国产色综合天天综合网 | 亚洲综合色噜噜狠狠| 免费国产羞羞网站视频| 熟女少妇内射日韩亚洲| 香蕉污视频在线观看| 国产日韩欧美大片| 国产精品 欧美在线| 色综合影院在线| 亚洲一区在线看| 国产精品一区二区三区在线免费观看| 成人黄色一级大片| 日韩国产欧美三级| 刘亦菲国产毛片bd| 97视频久久久| 国产精品对白刺激久久久| 精品国产电影一区二区| 91视频在线看| 这里只有精品国产| 性色av蜜臀av浪潮av老女人| 精品99在线视频| 日本高清视频免费在线观看| 丰满女人性猛交| 亚洲一区影院| 潘金莲一级淫片aaaaa免费看| 青春草在线视频免费观看| 91免费黄视频| 久色视频在线播放| 在线观看av网页| 三级电影在线看| av资源在线免费观看| 免费在线观看av网址| 国产成人综合欧美精品久久| 精品国精品国产自在久不卡| 麻豆91在线看| 国产毛片精品国产一区二区三区| 高清国产午夜精品久久久久久| 国产精品乱码人人做人人爱| 久久综合九色综合久久久精品综合| 97精品视频在线观看自产线路二| 99精品视频在线免费观看| 国产成人免费网站| 成人免费观看视频| 91小视频免费看| 久久夜色精品一区| 国产婷婷色一区二区三区四区| 26uuu国产一区二区三区| 91蜜桃在线观看| 国产欧美久久久精品影院| 国产精品美女久久久久av爽李琼 | 亚洲不卡一卡2卡三卡4卡5卡精品| 日本电影一区二区三区| 国产专区精品视频| 97精品国产91久久久久久| 欧美三级电影精品| 欧美日韩在线综合| 久久国产精品影视| 91亚洲精品丁香在线观看| 精品国产三级a∨在线| 青青草精品在线| 国产五月天婷婷| 国产ts人妖调教重口男| 国产露脸无套对白在线播放| 久久国产精品免费看| 久久久久久国产精品视频| 中出视频在线观看| 99热一区二区| 精品人妻一区二区三区蜜桃视频| 亚洲免费在线播放视频| 亚洲娇小娇小娇小| 农村妇女精品一二区| 精品一区二区国产| 国产在线视频卡一卡二| 亚洲精品乱码久久久久久蜜桃91 | 91久久精品无码一区二区| 看黄色一级大片| 91精品国产乱码久久久久| 无码人妻丰满熟妇奶水区码| 久草视频在线免费看| 精品人妻一区二区三区蜜桃视频| 日本一二三四区视频| 国产91美女视频| 中文字幕第21页| 国产成人一区二区三区别| 在线免费观看一区二区三区| 高清国产在线一区| 粉嫩av免费一区二区三区| 国产伦视频一区二区三区| 国产精品美女久久久久av超清| 国产精品黄视频| 国产精品高潮在线| 国产精品va在线播放我和闺蜜| 97在线观看视频国产| 97久久国产精品| 国产成人精彩在线视频九色| 欧美在线视频免费播放| 国产精品a久久久久久| 99影视tv| 久久精品欧美| 五月天亚洲综合小说网| 影音先锋在线亚洲| 国产九九九九九| 国产v亚洲v天堂无码久久久| 91九色在线观看视频| 性刺激的欧美三级视频| 欧美日韩理论片| 漂亮人妻被黑人久久精品| 国产美女永久免费无遮挡| 久久精品国产亚洲AV成人婷婷| 国产喷水在线观看| 国产欧美日韩另类| av中文字幕第一页| 天堂在线观看免费视频| 黑人精品欧美一区二区蜜桃| 高清在线不卡av| 中文字幕国产一区| 精品国产91乱高清在线观看| 精品久久久中文| 欧美一区二区三区在线| 欧美不卡一二三| 久久欧美在线电影| 91久久在线播放| 亚洲精品国产suv一区88| 欧美国产日韩在线播放| 精品中文字幕在线播放| 国产精品白嫩白嫩大学美女| www.日韩一区| 日韩av网站在线观看| www.视频一区| 一区二区在线观看av| 欧美日韩精品一区二区天天拍小说 | 亚洲自拍偷拍另类| 日韩国产成人精品| 亚洲欧美日韩在线| 欧美精品日韩一本| 日韩在线小视频| 91精品久久久久久久久久久久久| 黄色国产精品一区二区三区| 一卡二卡三卡视频| 美女露出粉嫩尿囗让男人桶| 青青操国产视频| 日本高清视频www| 久久综合av免费| 91福利国产成人精品照片| 日韩视频在线观看一区二区| 久久精品视频一| 成人欧美一区二区三区视频| 国产精品无码人妻一区二区在线 | 日韩视频免费在线播放| 国产精品久久久久久久av| 中文字字幕在线观看| 国产精品亚洲午夜一区二区三区| 亚洲男同性视频| 日韩国产精品视频| 97精品国产97久久久久久| 欧美日韩日本网| 伊人av在线播放| 久草手机在线观看| 国产麻豆欧美日韩一区| 精品免费在线视频| 色综合久久天天综线观看| 色视频一区二区三区| 男人女人拔萝卜视频| 中文字幕在线观看免费视频| 亚洲欧美另类一区| 18成人在线观看| 亚洲欧美日韩在线一区| aaa级精品久久久国产片| 中文久久久久久| 中日韩黄色大片| 久久精品国产精品亚洲综合| 色综合一区二区| 欧美大片网站在线观看| 亚洲成人精品电影在线观看| 国产九九热视频| 中文字幕第28页| 寂寞少妇一区二区三区| 午夜婷婷国产麻豆精品| 久久av在线看| 亚洲成人午夜在线| 黑人と日本人の交わりビデオ| 日韩av一级片| 欧美日韩午夜在线视频| 日本精品va在线观看| 男女啪啪的视频| 高h视频免费观看| 麻豆国产精品官网| 日韩午夜激情免费电影| 国产欧美日韩丝袜精品一区| 超碰在线人人爱| 久久久久久久久久一级|