久久福利_99r_国产日韩在线视频_直接看av的网站_中文欧美日韩_久久一

您的位置:首頁技術文章
文章詳情頁

Mybatis實現分表插件

瀏覽:2日期:2023-10-19 11:51:12
背景

事情是醬紫的,阿星的上級leader負責記錄信息的業務,每日預估數據量是15萬左右,所以引入sharding-jdbc做分表。

上級leader完成業務的開發后,走了一波自測,git push后,就忙其他的事情去了。

項目的框架是SpringBoot+Mybaits

出問題了

阿星負責的業務也開發完了,熟練的git pull,準備自測,單元測試run一下,上個廁所回來收工,就是這么自信。

Mybatis實現分表插件

回來后,看下控制臺,人都傻了,一片紅,內心不禁感嘆“如果這是股票基金該多好”。

出了問題就要解決,隨著排查深入,我的眉頭一皺發現事情并不簡單,怎么以前的一些代碼都報錯了?

Mybatis實現分表插件

隨著排查深入,最后跟到了Mybatis源碼,發現罪魁禍首是sharding-jdbc引起的,因為數據源是sharding-jdbc的,導致后續執行sql的是ShardingPreparedStatement。

這就意味著,sharding-jdbc影響項目的所有業務表,因為最終數據庫交互都由ShardingPreparedStatement去做了,歷史的一些sql語句因為sql函數或者其他寫法,使得ShardingPreparedStatement無法處理而出現異常。

關鍵代碼如下

Mybatis實現分表插件

發現問題后,阿星馬上就反饋給leader了。

Mybatis實現分表插件

唉,本來還想摸魚的,看來摸魚的時間是沒了,還多了一項任務。

分析

竟然交給阿星來做了,就擼起袖子開干吧,先看看分表功能的需求

支持自定義分表策略 能控制影響范圍 通用性

分表會提前建立好,所以不需要考慮表不存在的問題,核心邏輯實現,通過分表策略得到分表名,再把分表名動態替換到sql。

Mybatis實現分表插件

分表策略

為了支持分表策略,我們需要先定義分表策略抽象接口,定義如下

/** * @Author 程序猿阿星 * @Description 分表策略接口 * @Date 2021/5/9 */public interface ITableShardStrategy { /** * @author: 程序猿阿星 * @description: 生成分表名 * @param tableNamePrefix 表前綴名 * @param value 值 * @date: 2021/5/9 * @return: java.lang.String */ String generateTableName(String tableNamePrefix,Object value); /** * 驗證tableNamePrefix */ default void verificationTableNamePrefix(String tableNamePrefix){if (StrUtil.isBlank(tableNamePrefix)) { throw new RuntimeException('tableNamePrefix is null');} }}

generateTableName函數的任務就是生成分表名,入參有tableNamePrefix、value,tableNamePrefix為分表前綴,value作為生成分表名的邏輯參數。

verificationTableNamePrefix函數驗證tableNamePrefix必填,提供給實現類使用。

為了方便理解,下面是id取模策略代碼,取模兩張表

/** * @Author 程序猿阿星 * @Description 分表策略id * @Date 2021/5/9 */@Componentpublic class TableShardStrategyId implements ITableShardStrategy { @Override public String generateTableName(String tableNamePrefix, Object value) {verificationTableNamePrefix(tableNamePrefix);if (value == null || StrUtil.isBlank(value.toString())) { throw new RuntimeException('value is null');}long id = Long.parseLong(value.toString());//此處可以緩存優化return tableNamePrefix + '_' + (id % 2); }}

傳入進來的value是id值,用tableNamePrefix拼接id取模后的值,得到分表名返回。

控制影響范圍

分表策略已經抽象出來,下面要考慮控制影響范圍,我們都知道Mybatis規范中每個Mapper類對應一張業務主體表,Mapper類的函數對應業務主體表的相關sql。

阿星想著,可以給Mapper類打上注解,代表該Mpaaer類對應的業務主體表有分表需求,從規范來說Mapper類的每個函數對應的主體表都是正確的,但是有些同學可能不會按規范來寫。

假設Mpaaer類對應的是B表,Mpaaer類的某個函數寫著A表的sql,甚至是歷史遺留問題,所以注解不僅僅可以打在Mapper類上,同時還可以打在Mapper類的任意一個函數上,并且保證小粒度覆蓋粗粒度。

阿星這里自定義分表注解,代碼如下

/** * @Author 程序猿阿星 * @Description 分表注解 * @Date 2021/5/9 */@Target(value = {ElementType.TYPE,ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)public @interface TableShard { // 表前綴名 String tableNamePrefix(); //值 String value() default ''; //是否是字段名,如果是需要解析請求參數改字段名的值(默認否) boolean fieldFlag() default false; // 對應的分表策略類 Class<? extends ITableShardStrategy> shardStrategy();}

注解的作用范圍是類、接口、函數,運行時生效。

tableNamePrefix與shardStrategy屬性都好理解,表前綴名和分表策略,剩下的value與fieldFlag要怎么理解,分表策略分兩類,第一類依賴表中某個字段值,第二類則不依賴。

根據企業id取模,屬于第一類,此處的value設置企業id入參字段名,fieldFlag為true,意味著,會去解析獲取企業id字段名對應的值。

根據日期分表,屬于第二類,直接在分表策略實現類里面寫就行了,不依賴表字段值,value與fieldFlag無需填寫,當然你value也可以設置時間格式,具體看分表策略實現類的邏輯。

通用性

抽象分表策略與分表注解都搞定了,最后一步就是根據分表注解信息,去執行分表策略得到分表名,再把分表名動態替換到sql中,同時具有通用性。

Mybatis框架中,有攔截器機制做擴展,我們只需要攔截StatementHandler#prepare函數,即StatementHandle創建Statement之前,先把sql里面的表名動態替換成分表名。

Mybatis分表攔截器流程圖如下

Mybatis實現分表插件

Mybatis分表攔截器代碼如下,有點長哈,主流程看intercept函數就好了。

/** * @Author 程序員阿星 * @Description 分表攔截器 * @Date 2021/5/9 */@Intercepts({@Signature(type = StatementHandler.class,method = 'prepare',args = {Connection.class, Integer.class})})public class TableShardInterceptor implements Interceptor { private static final ReflectorFactory defaultReflectorFactory = new DefaultReflectorFactory(); @Override public Object intercept(Invocation invocation) throws Throwable {// MetaObject是mybatis里面提供的一個工具類,類似反射的效果MetaObject metaObject = getMetaObject(invocation);BoundSql boundSql = (BoundSql) metaObject.getValue('delegate.boundSql');MappedStatement mappedStatement = (MappedStatement)metaObject.getValue('delegate.mappedStatement');//獲取Mapper執行方法Method method = invocation.getMethod();//獲取分表注解TableShard tableShard = getTableShard(method,mappedStatement);// 如果method與class都沒有TableShard注解或執行方法不存在,執行下一個插件邏輯if (tableShard == null) { return invocation.proceed();}//獲取值String value = tableShard.value();//value是否字段名,如果是,需要解析請求參數字段名的值boolean fieldFlag = tableShard.fieldFlag();if (fieldFlag) { //獲取請求參數 Object parameterObject = boundSql.getParameterObject(); if (parameterObject instanceof MapperMethod.ParamMap) { //ParamMap類型邏輯處理MapperMethod.ParamMap parameterMap = (MapperMethod.ParamMap) parameterObject;//根據字段名獲取參數值Object valueObject = parameterMap.get(value);if (valueObject == null) { throw new RuntimeException(String.format('入參字段%s無匹配', value));}//替換sqlreplaceSql(tableShard, valueObject, metaObject, boundSql); } else { //單參數邏輯//如果是基礎類型拋出異常if (isBaseType(parameterObject)) { throw new RuntimeException('單參數非法,請使用@Param注解');}if (parameterObject instanceof Map){ Map<String,Object> parameterMap = (Map<String,Object>)parameterObject; Object valueObject = parameterMap.get(value); //替換sql replaceSql(tableShard, valueObject, metaObject, boundSql);} else { //非基礎類型對象 Class<?> parameterObjectClass = parameterObject.getClass(); Field declaredField = parameterObjectClass.getDeclaredField(value); declaredField.setAccessible(true); Object valueObject = declaredField.get(parameterObject); //替換sql replaceSql(tableShard, valueObject, metaObject, boundSql);} }} else {//無需處理parameterField //替換sql replaceSql(tableShard, value, metaObject, boundSql);}//執行下一個插件邏輯return invocation.proceed(); } @Override public Object plugin(Object target) {// 當目標類是StatementHandler類型時,才包裝目標類,否者直接返回目標本身, 減少目標被代理的次數if (target instanceof StatementHandler) { return Plugin.wrap(target, this);} else { return target;} } /** * @param object * @methodName: isBaseType * @author: 程序員阿星 * @description: 基本數據類型驗證,true是,false否 * @date: 2021/5/9 * @return: boolean */ private boolean isBaseType(Object object) {if (object.getClass().isPrimitive()|| object instanceof String|| object instanceof Integer|| object instanceof Double|| object instanceof Float|| object instanceof Long|| object instanceof Boolean|| object instanceof Byte|| object instanceof Short) { return true;} else { return false;} } /** * @param tableShard 分表注解 * @param value 值 * @param metaObject mybatis反射對象 * @param boundSql sql信息對象 * @author: 程序猿阿星 * @description: 替換sql * @date: 2021/5/9 * @return: void */ private void replaceSql(TableShard tableShard, Object value, MetaObject metaObject, BoundSql boundSql) {String tableNamePrefix = tableShard.tableNamePrefix();//獲取策略classClass<? extends ITableShardStrategy> strategyClazz = tableShard.shardStrategy();//從spring ioc容器獲取策略類ITableShardStrategy tableShardStrategy = SpringUtil.getBean(strategyClazz);//生成分表名String shardTableName = tableShardStrategy.generateTableName(tableNamePrefix, value);// 獲取sqlString sql = boundSql.getSql();// 完成表名替換metaObject.setValue('delegate.boundSql.sql', sql.replaceAll(tableNamePrefix, shardTableName)); } /** * @param invocation * @author: 程序猿阿星 * @description: 獲取MetaObject對象-mybatis里面提供的一個工具類,類似反射的效果 * @date: 2021/5/9 * @return: org.apache.ibatis.reflection.MetaObject */ private MetaObject getMetaObject(Invocation invocation) {StatementHandler statementHandler = (StatementHandler) invocation.getTarget();// MetaObject是mybatis里面提供的一個工具類,類似反射的效果MetaObject metaObject = MetaObject.forObject(statementHandler,SystemMetaObject.DEFAULT_OBJECT_FACTORY,SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY,defaultReflectorFactory);return metaObject; } /** * @author: 程序猿阿星 * @description: 獲取分表注解 * @param method * @param mappedStatement * @date: 2021/5/9 * @return: com.xing.shard.interceptor.TableShard */ private TableShard getTableShard(Method method, MappedStatement mappedStatement) throws ClassNotFoundException {String id = mappedStatement.getId();//獲取Classfinal String className = id.substring(0, id.lastIndexOf('.'));//分表注解TableShard tableShard = null;//獲取Mapper執行方法的TableShard注解tableShard = method.getAnnotation(TableShard.class);//如果方法沒有設置注解,從Mapper接口上面獲取TableShard注解if (tableShard == null) { // 獲取TableShard注解 tableShard = Class.forName(className).getAnnotation(TableShard.class);}return tableShard; }}

到了這里,其實分表功能就已經完成了,我們只需要把分表策略抽象接口、分表注解、分表攔截器抽成一個通用jar包,需要使用的項目引入這個jar,然后注冊分表攔截器,自己根據業務需求實現分表策略,在給對應的Mpaaer加上分表注解就好了。

Mybatis實現分表插件

實踐跑起來

這里阿星單獨寫了一套demo,場景是有兩個分表策略,表也提前建立好了

根據id分表 tb_log_id_0 tb_log_id_1 根據日期分表 tb_log_date_202105 tb_log_date_202106

預警:后面都是代碼實操環節,請各位讀者大大耐心看完(非Java開發除外)

TableShardStrategy定義

/** * @Author wx * @Description 分表策略日期 * @Date 2021/5/9 */@Componentpublic class TableShardStrategyDate implements ITableShardStrategy { private static final String DATE_PATTERN = 'yyyyMM'; @Override public String generateTableName(String tableNamePrefix, Object value) {verificationTableNamePrefix(tableNamePrefix);if (value == null || StrUtil.isBlank(value.toString())) { return tableNamePrefix + '_' +DateUtil.format(new Date(), DATE_PATTERN);} else { return tableNamePrefix + '_' +DateUtil.format(new Date(), value.toString());} }}** * @Author 程序猿阿星 * @Description 分表策略id * @Date 2021/5/9 */@Componentpublic class TableShardStrategyId implements ITableShardStrategy { @Override public String generateTableName(String tableNamePrefix, Object value) {verificationTableNamePrefix(tableNamePrefix);if (value == null || StrUtil.isBlank(value.toString())) { throw new RuntimeException('value is null');}long id = Long.parseLong(value.toString());//可以加入本地緩存優化return tableNamePrefix + '_' + (id % 2); }}Mapper定義

Mapper接口

/** * @Author 程序猿阿星 * @Description * @Date 2021/5/8 */@TableShard(tableNamePrefix = 'tb_log_date',shardStrategy = TableShardStrategyDate.class)public interface LogDateMapper { /** * 查詢列表-根據日期分表 */ List<LogDate> queryList(); /** * 單插入-根據日期分表 */ void save(LogDate logDate);}-------------------------------------------------------------------------------------------------/** * @Author 程序猿阿星 * @Description * @Date 2021/5/8 */@TableShard(tableNamePrefix = 'tb_log_id',value = 'id',fieldFlag = true,shardStrategy = TableShardStrategyId.class)public interface LogIdMapper { /** * 根據id查詢-根據id分片 */ LogId queryOne(@Param('id') long id); /** * 單插入-根據id分片 */ void save(LogId logId);}

Mapper.xml

<?xml version='1.0' encoding='UTF-8' ?><!DOCTYPE mapperPUBLIC '-//mybatis.org//DTD Mapper 3.0//EN''http://mybatis.org/dtd/mybatis-3-mapper.dtd'><mapper namespace='com.xing.shard.mapper.LogDateMapper'>//對應LogDateMapper#queryList函數 <select resultType='com.xing.shard.entity.LogDate'>selectid as id,comment as comment,create_date as createDatefromtb_log_date </select>//對應LogDateMapper#save函數 <insert >insert into tb_log_date(id, comment,create_date)values (#{id}, #{comment},#{createDate}) </insert></mapper>-------------------------------------------------------------------------------------------------<?xml version='1.0' encoding='UTF-8' ?><!DOCTYPE mapperPUBLIC '-//mybatis.org//DTD Mapper 3.0//EN''http://mybatis.org/dtd/mybatis-3-mapper.dtd'><mapper namespace='com.xing.shard.mapper.LogIdMapper'>//對應LogIdMapper#queryOne函數 <select resultType='com.xing.shard.entity.LogId'>selectid as id,comment as comment,create_date as createDatefromtb_log_idwhereid = #{id} </select>//對應save函數 <insert >insert into tb_log_id(id, comment,create_date)values (#{id}, #{comment},#{createDate}) </insert></mapper>執行下單元測試

日期分表單元測試執行

@Test void test() {LogDate logDate = new LogDate();logDate.setId(snowflake.nextId());logDate.setComment('測試內容');logDate.setCreateDate(new Date());//插入logDateMapper.save(logDate);//查詢List<LogDate> logDates = logDateMapper.queryList();System.out.println(JSONUtil.toJsonPrettyStr(logDates)); }

輸出結果

Mybatis實現分表插件

id分表單元測試執行

@Test void test() {LogId logId = new LogId();long id = snowflake.nextId();logId.setId(id);logId.setComment('測試');logId.setCreateDate(new Date());//插入logIdMapper.save(logId);//查詢LogId logIdObject = logIdMapper.queryOne(id);System.out.println(JSONUtil.toJsonPrettyStr(logIdObject)); }

輸出結果

Mybatis實現分表插件

小結一下

本文可以當做對Mybatis進階的使用教程,通過Mybatis攔截器實現分表的功能,滿足基本的業務需求,雖然比較簡陋,但是Mybatis這種擴展機制與設計值得學習思考。

有興趣的讀者也可以自己寫一個,或基于阿星的做改造,畢竟是簡陋版本,還是有很多場景沒有考慮到。

另外分表的demo項目,阿星放到了Gitee,大家按需自取

Gitee地址: https://gitee.com/jxncwx/shard

項目結構:

Mybatis實現分表插件

到此這篇關于Mybatis實現分表插件的文章就介紹到這了,更多相關Mybatis 分表插件內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Mybatis 數據庫
相關文章:
主站蜘蛛池模板: 欧美一级毛片久久99精品蜜桃 | 国产真实乱全部视频 | 久久免费福利视频 | 精品一区二区三区久久 | 人人玩人人干 | 91久久精品一区二区三区 | 亚洲国产91 | 一级全黄性色生活片 | 亚洲视频在线观看网站 | 97超碰在线播放 | 欧美亚洲免费 | 成人国产在线观看 | 正在播放国产一区 | 日本成人中文字幕 | 91久久国产综合久久91精品网站 | 91精品国产日韩91久久久久久 | 午夜精品一区二区三区在线观看 | 成人黄色在线观看 | 欧美日韩国产中文字幕 | 久久国产精品视频 | 午夜国产精品视频 | 一级片手机免费看 | 久久精品91久久久久久再现 | 久久国产一区 | 成人欧美一区二区三区 | 成人欧美 | 欧美日韩国产综合视频 | 亚洲国产精品综合久久久 | 成人欧美一区二区三区在线观看 | 亚洲综合大片69999 | 在线亚洲人成电影网站色www | 亚洲高清一区二区三区 | 成人影院av| 国产精品视频久久久 | 仙人掌旅馆在线观看 | 日韩欧美一区二区视频 | 免费观看成人性生生活片 | 四虎884a | 久草.com| 欧美www.| 大陆一级毛片免费视频观看 | 中文字幕av一区二区 | 日韩视频在线观看一区 | 日韩午夜免费 | 久久久久一区二区三区 | 国产精品久久久精品 | 久久首页 | 久久黄色网 | 日韩一二三 | 久久久久久国产精品 | а天堂中文最新一区二区三区 | 日韩欧美高清视频 | 中文字幕一区二区三区四区 | 欧美日韩电影一区二区三区 | 黄色精品 | 精品二三区 | 不卡一区 | 国产精品久久久99 | 国产精品久久国产精品 | 三级av | 免费观看一级黄色片 | 免费看毛片的网站 | 国产成人99久久亚洲综合精品 | 亚洲第一免费网站 | 一区二区日韩视频 | 亚洲一在线| 日本末发育嫩小xxxx | 亚洲欧美综合一区 | 国产欧美精品一区二区三区四区 | 欧美性猛交xxxx黑人猛交 | 风间由美一区二区三区在线观看 | 亚洲啊v在线 | 亚洲一区二区三 | 欧洲亚洲视频 | 影音先锋男人网 | 精品国产一区二区三区久久久蜜月 | 免费av观看 | 一区二区在线免费观看 | 精品毛片在线 | 欧美成人中文字幕 | 欧美午夜精品久久久 | 亚洲综合二区 | 午夜电影网 | 亚洲综合色自拍一区 | 国产网站在线播放 | 久久精品在线 | 国产成人精品亚洲777人妖 | 久久无码精品一区二区三区 | 欧美视频三级 | 男女视频在线观看 | 成年人网站在线免费看 | 国产欧美日韩综合精品 | 亚洲欧美激情视频 | 日韩欧美黄色 | 日韩欧美在线综合 | 成人午夜av | 91婷婷射| 国产高清一区 | 天天碰天天操 | 露娜同人18av黄漫网站 | 精品中文字幕在线观看 | 亚洲国产精品福利 | 久久亚洲一区二区三区四区 | 国产精久久久久久久妇剪断 | 久久久久久久久一区二区三区 | 日韩成人一区 | www.avtt天堂网 | 久久精品亚洲精品 | 麻豆国产露脸在线观看 | 久久99精品久久久久久按摩秒播 | 日韩欧美在线一区二区 | 亚洲欧美日韩在线一区二区三区 | 99久久夜色精品国产亚洲1000部 | 日本成人在线视频网站 | 性瘾调教校园h | 久久久久久久久国产精品 | 日韩中文不卡 | 精品免费视频 | 亚洲黄色免费观看 | 国产欧美一区二区三区在线看 | 国产精品久久久久国产a级 日韩在线二区 | 久久精品久久久久久 | 亚洲高清网 | 国产精品999 | 天天天操 | 日本久久网 | a级在线免费视频 | 日日干夜夜干 | jlzzjlzz国产精品久久 | 亚洲国产精品福利 | 男人的天堂亚洲 | 久久久久久久中文 | 成人练习生 | 日韩在线观看视频一区二区三区 | 国产小视频在线观看 | 午夜国产羞羞视频免费网站 | 欧美日韩午夜 | 久草综合网 | 久久久久久久久综合 | www.夜夜骑 | 日韩欧美国产一区二区三区 | 一 级 黄 色 片免费网站 | 色综合色综合 | 免费观看特级毛片 | 91嫩草在线 | 久久精品久久久 | 午夜精品久久久久久 | 国产综合精品 | 久久亚洲一区二区 | 日韩三级 | 亚洲精品一区中文字幕乱码 | 日韩在线视频一区 | 天堂资源在线 | 日韩综合网| 伊人久久国产 | 无码一区二区三区视频 | av免费在线观看网站 | 中文字幕av一区二区 | 久久激情网| 一级篇| 国产成人高清视频 | 九九免费视频 | 国产精品污www一区二区三区 | 国产午夜一区二区三区 | caoporn国产精品免费公开 | 国产综合视频在线观看 | 国产99在线播放 | 久久se精品一区精品二区 | 欧美狠狠操 | 亚洲91| 国产视频精品在线 | 欧美三区视频 | 亚洲午夜精品一区二区三区 | 欧洲一区二区三区 | 天天草天天插 | 一区二区三区久久 | 一区在线免费观看 | 国产最新精品视频 | 中文字幕婷婷 | 国产精成人 | 国产精品中文字幕在线 | 成人高清在线 | 亚洲欧美日韩电影 | 亚洲国产成人av好男人在线观看 | 国产精品成人一区二区三区夜夜夜 | 久热精品视频在线播放 | 日本中文字幕在线视频 | 国产午夜精品一区二区三区嫩草 | 91亚洲国产成人久久精品网站 | 国产精品视频 | 久久国产一区二区 | 国产单男| 羞羞视频网站在线看 | 成人xxx| 免费黄色在线视频网址 | 久久99国产精品久久99果冻传媒 | 91久久精品一区 | 青青草一区 | 久草热8精品视频在线观看 欧美全黄 | 搡女人真爽免费午夜网站 | 国产精品第一国产精品 | 亚洲国产成人久久一区二区三区 | 红桃av一区二区 | 亚洲不卡在线 | 亚洲成a人| 激情毛片| 免费观看一级视频 | 国产不卡视频在线观看 | 国产韩国精品一区二区三区 | 中文字幕亚洲一区二区三区 | 久久三区 | 在线91 | 国产三级精品三级 | 在线观看免费毛片视频 | 久久青 | 最新一级毛片 | 欧美日韩一区二区视频在线观看 | 中文字幕在线精品 | 欧美一区二 | 亚洲精品乱码 | 五月婷婷综合激情网 | 免费观看一区二区三区 | 婷婷国产在线观看 | 99riav在线| 天天色天天| 日韩网站免费观看 | 操久久| 在线观看91| 成人精品一区二区三区 | 日干夜操 | 天天摸夜夜操 | 一区在线免费观看 | 成人日韩| 一级大片一级一大片 | 国产偷国产偷精品高清尤物 | 日韩欧美视频一区二区三区 | 美女黄视频网站 | 亚洲一区二区免费在线观看 | 国产人妖在线 | 久久伊人青青草 | 亚洲精品一区二区三区四区高清 | 精品中文在线 | 亚洲不卡高清视频 | 精品国产一区二区三区成人影院 | 国产精成人 | 欧美精品二区 | 亚洲一区二区三区四区五区中文 | 日本福利视频免费观看 | 最近免费中文字幕在线视频2 | 精品一区二区三区免费看 | 三级网站在线播放 | 免费av片 | 国产亚洲精品久久久久动 | 亚洲精品一区二区三区麻豆 | 亚洲免费精品网站 | 久久久精品区 | 一区二区国产精品 | 国产精品99久久 | 九九综合 | 久草.com| 亚洲欧美日韩另类精品一区二区三区 | 麻豆色呦呦 | 综合色九九| 久久久香蕉 | 国产黄色免费网站 | 久久久精品一区 | 成人精品久久久 | 亚洲 中文 欧美 日韩 在线观看 | 久久精品日 | 华丽的挑战在线观看 | 日韩一二三区 | 久久久亚洲成人 | 欧美日韩亚洲国产综合 | 天天舔日日干 | 国产精品免费观看 | 欧美在线a | 久久久午夜爽爽一区二区三区三州 | 日本美女影院 | 午夜午夜精品一区二区三区文 | 亚洲av毛片 | 久久久毛片 | 日韩一区电影 | 日韩免费电影 | 91麻豆精品国产91久久久更新资源速度超快 | 国产黄色av | 日韩精品影院 | 综合天天 | 在线视频日韩 | 97精品在线 | 亚洲视频一区二区 | 激情婷婷| 日精品| 91人人| 成人久久久精品国产乱码一区二区 | 久久久久久久久久穴 | 国产在线一区二区三区 | 日韩欧美综合在线 | 中文字幕高清视频 | 羞羞视频免费看 | 国产伦精品一区二区三区在线 | 亚洲精品在线免费观看视频 | 国产精品国产精品国产专区不片 | 欧美一区二区 | xnxx 美女19 | 国产最新视频 | www.99日本精品片com | 色婷婷综合在线视频 | 欧美成在线观看 | 欧美成人精品一区二区三区 | 毛片在线免费 | 中文字幕日韩av | 国产精品久久久久久久福利院 | 欧美一区二区三区在线视频 | 91精品久久久久久久 | 天堂在线中文字幕 | 久久久久国产一级毛片 | 欧美日本在线观看 | www.久久.com | 欧美激情精品一区 | 久久久久久久影院 | 爱爱视频在线 | 免费一级片 | 精品国产一区二区三区久久久蜜月 | 国产欧美一区二区三区国产幕精品 | 一级片大全 | 亚州综合一区 | 精品久久国产老人久久综合 | 欧美黄色一区 | 国产日韩精品在线观看 | 麻豆91视频 | 狠狠爱天天操 | 欧美日韩国产在线 | 欧美日韩综合视频 | 国产一区二区三区 | 凹凸日日摸日日碰夜夜 | 亚洲成人网一区 | 国产成人在线一区二区 | 欧美激情一区二区三区 | 欧美lesbianxxxxhd视频社区 | 日本a视频 | 日韩视频免费 | 久久大陆| 亚洲欧美少妇 | 日韩av福利 | 日韩中文视频 | 亚洲一区二区三区四区 | 精品一区二区三区在线观看 | 91免费在线看 | 日本视频中文字幕 | 久久精品国产免费 | 国产综合一区二区 | 欧美一区二区三区 | 国产ts视频| 日韩一二三区 | 久久久久亚洲一区二区三区 | www.久久 | 亚洲网在线 | 亚洲欧美在线观看 | 精品视频久久久 | 国产一区二区三区网站 | 欧美日韩精品在线 | 成人激情视频 | 在线观看成人小视频 | 91九色视频pron | 久久天堂 | 香蕉二区| 国产高清在线精品一区二区三区 | 999久久久国产999久久久 | 日本男人的天堂 | 国产精品久久久久久久久久久久久久 | 久久这里只有精品免费 | 国产精品久久久久久久久动漫 | 精品国精品国产自在久不卡 | 国产精品原创av片国产免费 | 中文字幕成人av | av天天干| 91在线看片| 免费在线精品视频 | 成人精品一区二区三区 | 91午夜在线 | 一区在线播放 | 久久视频一区二区 | 久久首页 | 男人天堂视频网 | 精品久久久久久久人人人人传媒 | 精品久久久久久国产 | 在线视频a | 久久精品这里只有精品 | 久久久久久国产精品美女 | 91在线 | 亚洲 | 国产精品不卡视频 | 亚洲欧美在线播放 | 久久久精品影院 | 亚洲高清在线观看 | 一区二区久久久 | 激情久久久 | 九九天堂网 | 精品超碰 | 久久情趣视频 | 毛片网在线观看 | 久久久久久久av | 国产成人免费在线观看 | 亚洲成人一区 | 亚洲三级网站 | 国产精品一二 | 色呦呦网站在线观看 | 亚洲精品一区二区网址 | 亚洲精品一区在线观看 | 免费欧美视频 | 最新日韩免费 | 精品国产乱码久久久久久闺蜜 | www.日本精品 | 久久精品免费视频观看 | 欧美精品成人一区二区三区四区 | 日韩欧美一级 | 国产精品免费一区二区三区四区 | 黄色小视频网 | 久久国内免费视频 | 天天干天天操天天爽 | 欧洲成人在线视频 | 免费观看一级特黄欧美大片 | 国产欧美日韩一区 | 黄色片免费在线观看视频 | 亚洲精品电影在线观看 | 在线视频不卡一区 | 91春色| 久久一 | 日韩在线中文字幕 | 91午夜伦伦电影理论片 | 亚洲成a人v欧美综合天堂麻豆 | 九色在线观看 | 国产一区二区三区四区在线观看 | 国产一区二区三区免费 | 国产精品久久国产愉拍 | 99精品网站 | 国产免费一区 | 日韩精品1区2区3区 成人黄页在线观看 | 亚洲 欧美日韩 国产 中文 | 精品欧美一区二区三区 | 国产激情一区二区三区 | 精品三级在线观看 | 人人看人人插 | 色视频在线免费观看 | 欧美精品在线免费观看 | 伊人网伊人 | 特黄特黄a级毛片免费专区 av网站免费在线观看 | 欧美日一区二区 | 99精品欧美一区二区三区 | 福利视频一区 | 亚洲一区精品在线 | 黑人av| 狠狠操网站 | 99久久精品免费 | 成人精品在线观看 | 91亚洲国产成人久久精品网站 | 夜夜操天天操 | 欧美在线观看一区二区 | 欧美a在线 | 久久久久黄 | 国产伦精品一区二区三区四区视频 | 国产一区二区毛片 | 狠狠综合久久av一区二区小说 | 97伦理电影 | 国产精品欧美日韩 | 在线看片成人 | 精品国产一区二区三区久久久蜜月 | 午夜成人免费电影 | 国产精品1区2区3区 午夜视频网站 | 99久久免费精品国产男女性高好 | 欧洲亚洲精品久久久久 | av免费观看网站 | 97久久久国产精品 | av在线一区二区 | 国产精品日韩 | 国产精品美女久久久久aⅴ国产馆 | 免费观看毛片 | 久久久亚洲综合 | 国产精品国产三级国产aⅴ9色 | 日韩欧美精品区 | 成人免费共享视频 | 免费欧美一级 | 午夜av电影 | 午夜精品久久 | 中文字幕日韩一区 | 狠久久 | 国产精品欧美久久久久一区二区 | 一区二区三区国产在线观看 | 中文字幕第一页在线 | 欧日韩免费视频 | 日韩精品在线网站 | 久草电影网| 成人福利 | 久久激情五月丁香伊人 | 中文字幕国产 | 91久草视频 | 超碰免费在线观看 | 老司机午夜免费精品视频 | 亚洲国产成人av好男人在线观看 | 国产激情在线视频 | 日韩欧美国产网站 | 综合激情av| 欧美aaa大片 | 欧美精品一区二区三区蜜桃视频 | 麻豆亚洲| 中文字幕亚洲一区二区三区 | 亚洲一区综合 | 久久99精品久久久水蜜桃 | 亚洲性生活免费视频 | 高清一区二区三区视频 | 久久青草国产 | 国产一区免费视频 | 成人1区2区| 久久一区二区三 | 每日更新在线观看av | 成人精品一区 | 在线观看av片 | 国产乱码精品一区二区三 | 欧美日韩一区二区三 | 亚洲国产精品免费 | 国产成人精品一区二 | 日韩性视频 | 日韩免费 | 久久99国产精品 | 日韩性色视频 | 亚洲成人精品在线 | 亚洲精品久久久久久久久久久 | 日韩一区二区在线观看视频 | 亚洲一区二区久久 | 欧美日韩综合一区 | 日本精品一区二区三区在线观看 | 国产中文一区 | 亚洲国产高清高潮精品美女 | 99精品欧美一区二区三区 | 亚洲毛片在线 | 黄网在线观看 | 国产成人欧美一区二区三区的 | 日日摸夜夜添夜夜添高潮视频 | 欧美日一区| 性视频黄色 | 国产精品视频 | 国产一二区在线 | 国产精品美女久久久久久免费 | 丁香久久 | 综合一区二区三区 | 精品99在线 | 国产视频一区二区 | 日韩成人免费视频 | 狠狠91| 91av免费在线| 五月婷婷激情 | 精品一区二区在线观看 | 国产精品久久久久久亚洲调教 | 中文字幕亚洲精品 | 四虎永久免费影视 | 久久久久久毛片免费观看 | 日韩中文在线 | 欧美精品一区二区三区免费视频 | 日韩欧美理论片 | 亚洲天堂色2017 | 久久99精品国产91久久来源 | 欧美日韩综合 | 综合五月激情 | 91性高湖久久久久久久久网站 | 日韩成人精品视频在线观看 | 嫩草网站在线观看 | 在线观看免费黄色小视频 | 日韩免费视频一区二区 | 不卡的免费av | 免费网站国产 | 久热热热 | 91久久精品一区二区别 | 黄色天堂网 | 久久99精品久久久久久按摩秒播 | 亚洲一区二区久久 | 九九热免费看 | 天天天干干干 | 中文字幕在线视频观看 | 国产女人高潮视频在线观看 | 欧美高清一区 | 久色视频在线观看 | 精品久久一二三区 | 亚洲精品一区二区三区在线观看 | 欧美在线小视频 | 成人在线不卡 | 中文视频在线 | 国产欧美精品一区二区三区 | 久久99这里只有精品 | 视频在线一区 | 国产激情网站 | 欧美欧美欧美 | 噜噜噜噜噜色 | 亚洲精品www久久久久久广东 | 婷婷色av| 国产午夜精品久久久久免费视高清 | 久久成人免费 | 久久99精品视频 | av电影中文字幕在线观看 | 亚洲精品久久久久久久久久久 | 中文字幕一区在线观看视频 | 欧美精品免费在线观看 | 亚洲精品视频免费 | 色精品 | av午夜| 亚洲综合欧美日韩 | 欧美亚洲激情 | 91电影在线观看 | 日韩视频在线不卡 | 日韩高清不卡一区二区三区 | 99国产精品99久久久久久 | 黄色一级在线播放 | 性高湖久久久久久久久aaaaa | 在线观看中文字幕 | 久久99精品久久久久久久青青日本 | 日本视频一区二区三区 | 精品视频二区 |