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

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

淺談Mybatis SqlSession執行流程

瀏覽:2日期:2023-10-18 17:44:11
目錄Mybatis執行SQL流程SqlSessionExecutorMybatis之ExecutorMybatis之StatementHandler進入ResultSetHandlerMybatis執行SQL流程

在看源碼之前,我們需要了解一些基本知識,如果您沒有閱讀Mybatis SqlSessionFactory 初始化原理,可以先閱讀Mybatis SqlSessionFactory 初始化原理這篇文章,這用更有助于我們理解接下來的文章在看源碼之前,我們需要了解一些基本知識

SqlSession

SqlSession是一個接口,它有兩個實現類: - DefaultSqlSession:默認實現類 - SqlSessionManager:已經棄用的實現類,所以我們不需要關注他SqlSession是與數據庫交互的頂層類,通常與ThreadLocal綁定,一個會話使用一個SqlSession,SqlSession是線程不安全的,使用完畢需要close()

public class DefaultSqlSession implements SqlSession { private final Configuration configuration; private final Executor executor;}

SqlSession中最重要的兩個變量: - Configuration:核心配置類,也是初始化時傳過來的 - Executor:實際執行SQL的執行器

Executor

Executor是一個接口,有三個實現類 - BatchExecutor 重用語句,并執行批量更新 - ReuseExecutor 重用預處理語句prepared statements - SimpleExecutor 普通的執行器,默認使用

了解完基本知識后,我們接著往下看代碼。

當創建完SqlSessionFactory后,就可以創建SqlSession,然后使用SqlSession進行增刪改查:

// 1. 讀取配置文件,讀成字節輸入流,注意:現在還沒解析InputStream resourceAsStream = Resources.getResourceAsStream('sqlMapConfig.xml');// 2. 解析配置文件,封裝Configuration對象 創建DefaultSqlSessionFactory對象SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);SqlSession sqlSession = sqlSessionFactory.openSession();List<Object> objects = sqlSession.selectList('namespace.id');

我們先去看openSession()方法,創建了SqlSession

//6. 進入openSession方法@Overridepublic SqlSession openSession() { //getDefaultExecutorType()傳遞的是SimpleExecutor // level:數據庫事物級別,null return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);}//7. 進入openSessionFromDataSource。//ExecutorType 為Executor的類型,TransactionIsolationLevel為事務隔離級別,autoCommit是否開啟事務//openSession的多個重載方法可以指定獲得的SeqSession的Executor類型和事務的處理private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) { Transaction tx = null; try {// 獲得 Environment 對象final Environment environment = configuration.getEnvironment();// 創建 Transaction 對象final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);// 創建 Executor 對象final Executor executor = configuration.newExecutor(tx, execType);// 創建 DefaultSqlSession 對象return new DefaultSqlSession(configuration, executor, autoCommit); } catch (Exception e) {// 如果發生異常,則關閉 Transaction 對象closeTransaction(tx); // may have fetched a connection so lets call close()throw ExceptionFactory.wrapException('Error opening session. Cause: ' + e, e); } finally {ErrorContext.instance().reset(); }}

通過源碼可以清晰的看到,會話工廠創建了Environment,Transaction,Executor,DefaultSqlSession對象,并且對于會話對象來說,他的autoCommit默認為false,默認不自動提交。

然后我回到原來的代碼,接著就需要使用SqlSession進行增刪改查操作了

所以我們進入selectList()查看

//8.進入selectList方法,多個重載方法@Overridepublic <E> List<E> selectList(String statement) { return this.selectList(statement, null);}@Overridepublic <E> List<E> selectList(String statement, Object parameter) { return this.selectList(statement, parameter, RowBounds.DEFAULT);}@Overridepublic <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) { try {// 獲得 MappedStatement 對象MappedStatement ms = configuration.getMappedStatement(statement);// 執行查詢return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER); } catch (Exception e) {throw ExceptionFactory.wrapException('Error querying database. Cause: ' + e, e); } finally {ErrorContext.instance().reset(); }}

selectList有多個重載方法,進入到最終方法后,我們可以看到它做了兩件事

通過statementId,從Configuration中取MappedStatement對象,就是存放了sql語句,返回值類型,輸入值類型的對象 然后委派Executor執行器去執行具體的增刪改查方法

所以,對于實際JDBC的操作,我們還需要進入Executor中查看

Mybatis之Executor

我們繼續從剛剛selectList源碼中,進入Executor查看

return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);

//此方法在SimpleExecutor的父類BaseExecutor中實現@Overridepublic <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException { //根據傳入的參數動態獲得SQL語句,最后返回用BoundSql對象表示 BoundSql boundSql = ms.getBoundSql(parameter); //為本次查詢創建緩存的Key CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql); // 查詢 return query(ms, parameter, rowBounds, resultHandler, key, boundSql);}

拆分成了三大步:

(1)先調用MappedStatement的getBoundSql方法,獲取解析后的SQL語句,解析工作是由SqlSourceBuilder完成的

什么叫解析后的SQL語句呢?因為Mybatis編寫SQL語句時,會用到動態SQL,比如#{}占位符,這種占位符JDBC是不認識的,所以需要將其轉換成?占位符,并且將其內部的字段名存儲起來,后面填充參數的時候好使用反射獲取值。

/** * 執行解析原始 SQL ,成為 SqlSource 對象 * * @param originalSql 原始 SQL * @param parameterType 參數類型 * @param additionalParameters 附加參數集合。可能是空集合,也可能是 {@link org.apache.ibatis.scripting.xmltags.DynamicContext#bindings} 集合 * @return SqlSource 對象 */public SqlSource parse(String originalSql, Class<?> parameterType, Map<String, Object> additionalParameters) { // 創建 ParameterMappingTokenHandler 對象 ParameterMappingTokenHandler handler = new ParameterMappingTokenHandler(configuration, parameterType, additionalParameters); // 創建 GenericTokenParser 對象 GenericTokenParser parser = new GenericTokenParser('#{', '}', handler); // 執行解析 String sql = parser.parse(originalSql); // 創建 StaticSqlSource 對象 return new StaticSqlSource(configuration, sql, handler.getParameterMappings());}

上面代碼就可以看到,會將拆分#{和},進行解析

(2)根據查詢條件,創建緩存key,用來接下來去緩存查找是否有已經執行過的結果

(3)調用重載query()方法

接著我們進入重載方法查看:

@Override public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {ErrorContext.instance().resource(ms.getResource()).activity('executing a query').object(ms.getId());// 已經關閉,則拋出 ExecutorException 異常if (closed) { throw new ExecutorException('Executor was closed.');}// 清空本地緩存,如果 queryStack 為零,并且要求清空本地緩存。if (queryStack == 0 && ms.isFlushCacheRequired()) { clearLocalCache();}List<E> list;try { // queryStack + 1 queryStack++; // 從一級緩存中,獲取查詢結果 list = resultHandler == null ? (List<E>) localCache.getObject(key) : null; // 獲取到,則進行處理 if (list != null) {handleLocallyCachedOutputParameters(ms, key, parameter, boundSql); // 獲得不到,則從數據庫中查詢 } else {list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql); }} finally { // queryStack - 1 queryStack--;}if (queryStack == 0) { // 執行延遲加載 for (DeferredLoad deferredLoad : deferredLoads) {deferredLoad.load(); } // issue #601 // 清空 deferredLoads deferredLoads.clear(); // 如果緩存級別是 LocalCacheScope.STATEMENT ,則進行清理 if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {// issue #482clearLocalCache(); }}return list; }

主要的邏輯:

從一級緩存取數據,如果有直接使用緩存的進行接下來的操作 如果沒有,從數據庫查詢

進入queryFromDatabase()方法:

// 從數據庫中讀取操作private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException { List<E> list; // 在緩存中,添加占位對象。此處的占位符,和延遲加載有關,可見 `DeferredLoad#canLoad()` 方法 localCache.putObject(key, EXECUTION_PLACEHOLDER); try {// 執行讀操作list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql); } finally {// 從緩存中,移除占位對象localCache.removeObject(key); } // 添加到緩存中 localCache.putObject(key, list); // 暫時忽略,存儲過程相關 if (ms.getStatementType() == StatementType.CALLABLE) {localOutputParameterCache.putObject(key, parameter); } return list;}@Overridepublic <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException { Statement stmt = null; try {Configuration configuration = ms.getConfiguration();// 傳入參數創建StatementHanlder對象來執行查詢StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);// 創建jdbc中的statement對象stmt = prepareStatement(handler, ms.getStatementLog());// 執行 StatementHandler ,進行讀操作return handler.query(stmt, resultHandler); } finally {// 關閉 StatementHandler 對象closeStatement(stmt); }}

通過代碼可以看到,對于實際與JDBC交互的代碼,Executor也懶得搞,又像SqlSession一樣,委派給小弟StatementHandler了。

Mybatis之StatementHandler

我們從剛剛的Executor的代碼查看

@Overridepublic <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException { Statement stmt = null; try {Configuration configuration = ms.getConfiguration();// 傳入參數創建StatementHanlder對象來執行查詢StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);// 創建jdbc中的statement對象stmt = prepareStatement(handler, ms.getStatementLog());// 執行 StatementHandler ,進行讀操作return handler.query(stmt, resultHandler); } finally {// 關閉 StatementHandler 對象closeStatement(stmt); }}

可以看到,這里創建完StatementHandler后,回調用prepareStatement()方法,用來創建Statement對象

我們進入prepareStatement方法中查看

// 初始化 StatementHandler 對象private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException { Statement stmt; // 獲得 Connection 對象 Connection connection = getConnection(statementLog); // 創建 Statement 或 PrepareStatement 對象 stmt = handler.prepare(connection, transaction.getTimeout()); // 設置 SQL 上的參數,例如 PrepareStatement 對象上的占位符 handler.parameterize(stmt); return stmt;}@Overridepublic void parameterize(Statement statement) throws SQLException { //使用ParameterHandler對象來完成對Statement的設值 parameterHandler.setParameters((PreparedStatement) statement);}

這里可以看到,它實際是使用ParameterHandler來設置Statement的參數

@Overridepublic void setParameters(PreparedStatement ps) { ErrorContext.instance().activity('setting parameters').object(mappedStatement.getParameterMap().getId()); // 遍歷 ParameterMapping 數組 List<ParameterMapping> parameterMappings = boundSql.getParameterMappings(); if (parameterMappings != null) {for (int i = 0; i < parameterMappings.size(); i++) { // 獲得 ParameterMapping 對象 ParameterMapping parameterMapping = parameterMappings.get(i); if (parameterMapping.getMode() != ParameterMode.OUT) {// 獲得值Object value;String propertyName = parameterMapping.getProperty();if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params value = boundSql.getAdditionalParameter(propertyName);} else if (parameterObject == null) { value = null;} else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) { value = parameterObject;} else { MetaObject metaObject = configuration.newMetaObject(parameterObject); value = metaObject.getValue(propertyName);}// 獲得 typeHandler、jdbcType 屬性TypeHandler typeHandler = parameterMapping.getTypeHandler();JdbcType jdbcType = parameterMapping.getJdbcType();if (value == null && jdbcType == null) { jdbcType = configuration.getJdbcTypeForNull();}// 設置 ? 占位符的參數try { typeHandler.setParameter(ps, i + 1, value, jdbcType);} catch (TypeException | SQLException e) { throw new TypeException('Could not set parameters for mapping: ' + parameterMapping + '. Cause: ' + e, e);} }} }}

這段代碼的主要目的,就是獲取入參,然后根據值,來設置?占位符的參數

TypeHandler是具體進行參數設置的對象

所以handler.prepare(connection, transaction.getTimeout());方法,就是使用ParameterHandler來對占位符位置的參數進行值設置

然后我們回到Executor,查看handler.query()方法

@Overridepublic <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException { PreparedStatement ps = (PreparedStatement) statement; // 執行查詢 ps.execute(); // 處理返回結果 return resultSetHandler.handleResultSets(ps);}

代碼很簡單,這里直接使用JDBC的PreparedStatement來進行SQL執行,然后使用ResultSetHandler進行結果數據封裝處理。

進入ResultSetHandler

@Overridepublic List<Object> handleResultSets(Statement stmt) throws SQLException { ErrorContext.instance().activity('handling results').object(mappedStatement.getId()); // 多 ResultSet 的結果集合,每個 ResultSet 對應一個 Object 對象。而實際上,每個 Object 是 List<Object> 對象。 // 在不考慮存儲過程的多 ResultSet 的情況,普通的查詢,實際就一個 ResultSet ,也就是說,multipleResults 最多就一個元素。 final List<Object> multipleResults = new ArrayList<>(); int resultSetCount = 0; // 獲得首個 ResultSet 對象,并封裝成 ResultSetWrapper 對象 ResultSetWrapper rsw = getFirstResultSet(stmt); // 獲得 ResultMap 數組 // 在不考慮存儲過程的多 ResultSet 的情況,普通的查詢,實際就一個 ResultSet ,也就是說,resultMaps 就一個元素。 List<ResultMap> resultMaps = mappedStatement.getResultMaps(); int resultMapCount = resultMaps.size(); validateResultMapsCount(rsw, resultMapCount); // 校驗 while (rsw != null && resultMapCount > resultSetCount) {// 獲得 ResultMap 對象ResultMap resultMap = resultMaps.get(resultSetCount);// 處理 ResultSet ,將結果添加到 multipleResults 中handleResultSet(rsw, resultMap, multipleResults, null);// 獲得下一個 ResultSet 對象,并封裝成 ResultSetWrapper 對象rsw = getNextResultSet(stmt);// 清理cleanUpAfterHandlingResultSet();// resultSetCount ++resultSetCount++; } // 因為 `mappedStatement.resultSets` 只在存儲過程中使用,本系列暫時不考慮,忽略即可 // ··· // 如果是 multipleResults 單元素,則取首元素返回 return collapseSingleResultList(multipleResults);} // 處理 ResultSet ,將結果添加到 multipleResults 中private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, List<Object> multipleResults, ResultMapping parentMapping) throws SQLException { try {// 暫時忽略,因為只有存儲過程的情況,調用該方法,parentMapping 為非空if (parentMapping != null) { handleRowValues(rsw, resultMap, null, RowBounds.DEFAULT, parentMapping);} else { // 如果沒有自定義的 resultHandler ,則創建默認的 DefaultResultHandler 對象 if (resultHandler == null) {// 創建 DefaultResultHandler 對象DefaultResultHandler defaultResultHandler = new DefaultResultHandler(objectFactory);// 處理 ResultSet 返回的每一行 RowhandleRowValues(rsw, resultMap, defaultResultHandler, rowBounds, null);// 添加 defaultResultHandler 的處理的結果,到 multipleResults 中multipleResults.add(defaultResultHandler.getResultList()); } else {// 處理 ResultSet 返回的每一行 RowhandleRowValues(rsw, resultMap, resultHandler, rowBounds, null); }} } finally {// issue #228 (close resultsets)// 關閉 ResultSet 對象closeResultSet(rsw.getResultSet()); }}

代碼比較多,實際最重要的代碼就是

// 添加 defaultResultHandler 的處理的結果,到 multipleResults 中multipleResults.add(defaultResultHandler.getResultList());

將處理后的結果封裝到集合中返回,這樣基本Mybatis邏輯就走完了.

我們來回顧一下,都用到了哪些類

淺談Mybatis SqlSession執行流程

簡單總結SqlSessionFactoryBuilder:

解析核心配置文件,創建Configuration XMLConfigBuilder.parse():解析核心配置文件XMLMapperBuilder.parse():解析映射配置文件MappedStatement 創建SqlSessionFactory,默認創建DefaultSqlSessionFactory

SqlSessionFactory:

openSession():構建Executor,SqlSession等

SqlSession:

根據statementId獲取MappedStatement 委派給Executor執行器執行

Executor:

使用SqlSourceBuilder,將SQL解析成JDBC認可的 查詢緩存,是否存在結果 結果不存在,委派給StatementHandler處理器

StatementHandler:

PreparedStatement:處理參數,將參數賦值到占位符上 TypeHandler:具體設置值的類 ResultSetHandler:封裝結果集,封裝成設置的返回值類型 TypeHandler:根據結果集,取出對應列

到此這篇關于淺談Mybatis SqlSession執行流程的文章就介紹到這了,更多相關Mybatis SqlSession執行流程內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Mybatis 數據庫
相關文章:
主站蜘蛛池模板: 国产高清精品一区二区三区 | 国产精品视频 | 国产精品九九九 | 欧美日韩视频 | 精品日韩一区二区三区 | 日韩在线不卡 | 日韩精品一区二区三区四区视频 | av中文字幕在线播放 | 伊人久久综合 | 久久99精品久久久 | 色69av| 在线观看欧美一区 | 亚洲一区二区免费 | 亚洲精品免费视频 | www.久久久| 国产依人| 精品av | 国产精品免费一区 | 天堂在线中文 | 精品日韩一区 | 久久久国产精品入口麻豆 | 91精品国产九九九久久久亚洲 | 蜜桃视频一区 | 亚洲高清在线 | 精品国产精品 | 在线激情av | 九草在线 | 国产激情一区二区三区 | 91亚洲国产成人久久精品网站 | 日本精品免费观看 | 国产xnxx | 欧美视频免费在线 | 在线视频 亚洲 | 国产成人亚洲综合 | 亚洲欧洲一区二区 | 99动漫| 色女人av| 日韩在线视频观看免费 | 精品婷婷 | 久久色av | 久久久婷 | 亚洲午夜精品视频 | 黄色大片成人 | 成人片免费看 | 亚洲啊v在线| 欧美一区二区三区免费电影 | 亚洲一区免费视频 | www中文字幕 | 羞羞视频在线观免费观看 | 欧美色综合 | 性处破╳╳╳高清欧美 | 永久精品 | 国产精品永久免费 | 免费黄色小视频 | 亚洲精品久久 | 国产一级黄| 久久国产美女 | 国产亚洲一区二区三区在线 | 国产精品毛片一区二区三区 | 亚洲精品美女久久久 | 欧美一区二区另类 | 国产欧美日韩 | 91一区二区在线 | 久久国产精品久久久久久 | 一区二区在线电影 | 亚洲精品一区二区三区精华液 | 欧美中文字幕 | 午夜精品视频在线观看 | 国产精品自产拍在线观看桃花 | 99riav国产精品 | 蜜臀精品| 国产高清免费视频 | 亚洲一区在线观看视频 | 久久久久国产亚洲日本 | 一区不卡 | 毛片免费在线观看 | 超级碰在线 | 精品久久久一区 | 中文成人在线 | 久久久www成人免费精品 | 99爱免费观看国语 | 欧美成年黄网站色视频 | 亚洲视频在线观看 | 国产亚洲精品久久久久动 | 国产成人精品一区二区 | 久久久久久一区 | 亚洲一区在线视频 | 日本天天操 | 欧美一级片在线 | 日韩有码在线播放 | 噜噜噜在线观看免费视频日本 | 国产1区2区 | 99热少妇| 精品国产三级 | 国产婷婷| 亚洲精品视 | 国产视频福利一区 | 精品中文在线 | 欧美亚洲视频在线观看 | 国产中文字幕一区 | 中文字幕在线一区 | 美女国产精品 | 欧美黑人一级爽快片淫片高清 | 99视频在线 | 色就是色网站 | 精品国模一区二区三区欧美 | 欧美一区二区黄色片 | 欧美黄色一区 | 中文字幕99| 国产亚洲精品精品国产亚洲综合 | 国产精品久久久久久久久福交 | 成人影院www在线观看 | 亚洲综合首页 | 狠狠做深爱婷婷综合一区 | 日本少妇bbbb爽爽bbb美 | 国产精品成人在线 | 久久精品这里只有精品 | 国产伦精品一区二区三区四区视频 | 综合久久99| 夜夜爆操| 一级黄色毛片子 | 色精品 | 欧美天天| 婷婷久久综合九色综合绿巨人 | 一区二区三区视频在线观看 | 艳妇荡乳豪妇荡淫 | 日韩中文字幕在线观看 | 91aiai| 色在线播放| a性片| 午夜精品久久久久久久久久久久 | 亚洲视频中文字幕 | 亚洲成人黄色 | 精品久久久久久久久久久久久久 | 色黄视频在线观看 | 免费av手机在线观看 | 欧美一区二区三区在线 | 91在线区 | 亚洲精品久久久久久下一站 | 久久综合一区二区 | 夜夜操操操 | 亚洲精品一二三 | 91av原创 | 亚洲综合成人网 | 九九九在线| 欧美精品日韩 | 99re热精品视频 | 国产一区| 日韩视频区 | 成人午夜网 | 午夜精品一区二区三区在线 | 国产欧美在线观看 | 久综合网 | 久久久91精品国产一区二区三区 | 亚洲精品三级 | 天天干天天干天天干天天射 | 国产区视频在线观看 | 亚洲一区二区三区四区在线 | 日韩和的一区二区 | 亚洲人网站 | 成人免费一区二区三区视频网站 | 一区二区蜜桃 | 美女黄视频网站 | 老司机福利在线观看 | 亚洲影视一区二区 | 综合伊人久久 | 国产精品久久久久久久久久东京 | 国产精品久久久久aaaa九色 | 日韩激情欧美 | 国产成人精品亚洲777人妖 | 国产成人av一区二区三区 | 综合久久亚洲 | 啊v在线| 丁香久久| 久久久久黄 | 精品久久久久久久久久久院品网 | 久久伊人影院 | 欧美一区2区三区4区公司二百 | 综合一区二区三区 | 91视频播放 | 久草在线 | 欧美专区在线 | 午夜精品久久久久久久久久久久久 | 国产午夜精品一区二区三区嫩草 | 一级毛片观看 | 极品av | 中文字幕视频三区 | 亚洲精品一区二区三区99 | 国产精品99 | 91视频18 | 欧美精品在线免费观看 | 国产精品国产精品国产专区不片 | 国产视频第一页 | 狠狠综合久久av一区二区小说 | 久草福利 | 精品视频二区三区 | 精品国产不卡一区二区三区 | 免费看国产一级特黄aaaa大片 | 亚洲a网站 | 亚洲一区综合 | 精品综合久久 | 午夜久久乐 | 国产一区久久精品 | 精品久久久久久久久久久 | 99re6在线视频精品免费 | 久操综合 | 一级色视频 | 老司机深夜福利在线观看 | 欧美一区二区三区国产精品 | 美日一级毛片 | 成人精品鲁一区一区二区 | 亚洲欧洲精品视频 | 国产偷录视频叫床高潮对白 | 久草热8精品视频在线观看 黄色片网站视频 | 噜噜噜在线视频 | 免费看国产一级片 | 91大神xh98hx在线播放 | 成年免费视频 | 亚洲成av人片在线观看 | 激情网页| 亚洲成人精品在线观看 | 精品国产区| 日韩久久久久久 | 欧美精品一区视频 | 91精品国产综合久久国产大片 | 一级a毛片 | 久免费视频 | 久久中文字幕一区 | 草久久久 | www久久精品| 免费观看黄色一级大片 | 久久久精彩视频 | 在线免费看a | 国产午夜视频 | 国产日韩欧美精品一区二区三区 | 中文字幕日韩欧美一区二区三区 | 成人午夜视频在线 | 在线免费中文字幕 | 在线观看成人网 | 91国产精品| 欧美激情网址 | 欧美成人a | 亚洲欧洲视频在线 | 国产精品成人一区二区 | 中文字幕日韩一区二区不卡 | 久久成人精品一区二区三区 | 欧美xxxⅹ性欧美大片 | 日韩国产在线观看 | 精品久久一区二区三区 | 国产一级一级特黄女人精品毛片 | 欧美日韩激情一区二区三区 | 精品在线不卡 | 日韩精品一区二区三区在线观看 | 在线欧美亚洲 | 欧美黄色一区 | 奇米av在线 | 国产日韩一区二区三区 | 亚洲一区国产精品 | 欧美综合一区二区 | 午夜久久久 | 一级在线看 | 亚洲日本精品视频 | 九色91在线 | 亚洲第一福利视频 | 男女www视频 | 日日操夜夜操天天操 | 精品国产一区二区三区性色 | 国产91麻豆视频 | 成人午夜视频在线观看 | 久久久久久91 | 亚洲人成在线播放 | 91社区在线高清 | 久久精品高清 | 中文字幕成人 | 99视频免费观看 | 中文成人在线 | 操操操操网 | 激情91| 日韩在线不卡 | 国产成人精品免费视频大全最热 | 97国产精品视频人人做人人爱 | 国产成人亚洲精品 | 最新国产在线视频 | 中文字幕在线资源 | 久久婷婷麻豆国产91天堂 | 国产美女视频一区 | 日韩欧美在线视频 | 先锋影音av资源站 | 精品中文字幕一区二区三区 | 日韩在线视频观看 | 91免费电影| 999国内精品永久免费视频 | 国产一级视频免费播放 | 国产欧美精品一区二区色综合 | 国产 日韩 欧美 中文 在线播放 | 日本高清中文字幕 | 国产精品亚洲精品日韩已方 | 午夜影视| 亚洲一区在线视频 | 久久久久久亚洲精品 | 久久精品国产亚洲blacked | 91午夜在线| 亚洲国产视频一区 | 日韩成人av在线 | 免费看国产一级特黄aaaa大片 | 亚洲成人国产精品 | 国产精品美女久久久久久久久久久 | 欧美久久一区 | 成人在线小视频 | 日韩精品视频在线观看一区二区 | 91精品国产欧美一区二区成人 | 蜜桃免费视频 | 中文字幕在线资源 | 午夜在线视频 | 国产福利在线免费 | 国产成人精品在线观看 | 亚洲一区二区三区 | 亚洲乱码国产乱码精品精 | 成人免费视频观看 | 亚洲网站在线观看 | 亚洲成人黄色 | 成人福利在线观看 | 韩国精品一区 | 最近中文字幕在线视频1 | 久久精品久久久久 | 国产亚洲精品久久久久久久久 | 久久99精品视频 | 午夜大片网 | 欧洲一级毛片 | 色黄视频在线观看 | 日本国产一区二区 | 久久久影视 | 97国产在线 | 伊人免费视频 | 免费一二二区视频 | 欧美久久久久久久久久 | 国产精品一区二 | 亚洲欧美在线综合 | 男女视频在线免费观看 | 欧洲成人一区 | 欧美日韩一区二区视频在线观看 | 成人欧美一区二区三区在线播放 | 99re6热只有精品免费观看 | 日韩精品在线观看视频 | 久精品在线| 国产成人精品免高潮在线观看 | 国产亚洲精品久久久久动 | 视频一区 国产精品 | 精品三级在线观看 | 国产特级毛片aaaaaa毛片 | 免费一区二区三区 | 97天堂| h小视频 | 欧美成人精品一区二区男人看 | 99精品一区二区 | 91在线视频 | 欧美精品一二三区 | 91免费电影 | 在线播放亚洲 | 国产一区二区三区 | 巨大黑人极品videos精品 | 欧美free性丝袜xxxxhd | 久久天堂 | 欧美最猛性xxxxx亚洲精品 | 欧美日韩黄色一级片 | 午夜精 | 亚洲综合二区 | 国产精品s色 | 青青久在线视频 | 亚洲av毛片 | 日韩亚洲视频 | 狠狠操天天操 | 亚洲专区国产精品 | 一区二区影院 | 国产精品s色| 欧美另类专区 | 国产免费高清 | 精品一区二区av | 久久狠狠 | 龙珠z国语291集普通话 | 国产不卡免费 | 国产欧美精品一区二区三区四区 | 亚洲色图一区二区三区 | 亚洲 激情 在线 | 亚洲精品国产第一综合99久久 | 亚洲精品在线免费看 | 午夜精品网站 | 欧美亚洲二区 | 久久亚洲国产精品 | 三级色网站 | 中文字幕在线观看一区二区三区 | 精品久久精品 | 久久国产一区二区三区 | 天堂精品一区二区三区 | 亚洲第一男人天堂 | 午夜精品一区二区三区免费视频 | 免费一区二区 | 午夜视频在线播放 | 精品久久久久久久久久久久久久 | 国产乱叫456 | 国产亚洲一区二区三区 | 一级视频网站 | 日韩大尺度电影在线观看 | 欧美亚洲综合久久 | 日韩精品日韩激情日韩综合 | 精品国产免费久久久久久尖叫 | 操操操操操操操操操操操操操操 | 日本久久二区 | 在线观看中文 | 特黄一级 | 日本一区二区视频 | 日韩在线区 | 久久精品成人免费视频 | 日韩av一区二区在线观看 | 黄色国产一级视频 | 91在线 | 亚洲 | 国产乱码精品一区二区三区手机版 | 欧美精产国品一二三区 | 免费一区 | 免费在线观看一级毛片 | 91看片官网| 欧美一区二区日韩 | 羞羞视频网站免费看 | 精品免费| 国产精品99久久免费观看 | 亚洲免费一区 | 超碰免费在线观看 | 色接久久 | 亚洲人成人一区二区在线观看 | 狠狠操操| 91精品久久久久久久久久入口 | 在线中文字幕av | 日本中文字幕一区二区 | 亚洲国产成人精品女人 | 欧美激情一区二区 | 91一区| 亚洲国产高清在线 | 日本电影网址 | 亚洲视频免费 | 欧美精品v国产精品v日韩精品 | 成人一区二区在线 | 国产网站在线播放 | 日韩欧美不卡 | 国产一区二区精品在线观看 | 午夜精品视频 | 毛片在线免费 | 国产精品99久久久久久久vr | 国产成人精品一区二区 | 欧美精品一二三 | 91精品一区二区 | 欧美中文一区 | 欧美日韩精品一区二区三区 | 日本1区2区 | 日韩国产| 毛片入口 | 99免费视频 | 成人黄色一区 | 成人a在线视频免费观看 | 亚州精品天堂中文字幕 | 午夜无码国产理论在线 | 欧美区亚洲区 | 最新国产毛片 | 欧美精品一级二级 | 精品欧美一区二区三区久久久小说 | 亚洲国产精品久久久 | 久久国产精品视频观看 | 91精品国产91久久久久久吃药 | 一区二区三区免费在线 | 狠狠躁夜夜躁人人爽天天天天97 | 中文字幕一区在线观看视频 | 久久亚洲国产精品 | 久久不卡日韩美女 | 日本一本在线 | 伊人网站| 国产精品久久久久久一级毛片 | 一片毛片 | 色综合久久88色综合天天 | 欧美日韩在线看 | 日韩在线观看视频免费 | 久久国产精品一区二区 | 福利网在线 | 亚洲精品久久久久久久久久久久久 | 欧美在线操 | 欧美日韩亚洲高清 | 97av| 免费看一区二区三区 | 国产精品欧美一区二区三区 | 精品国产31久久久久久 | 91九色视频在线 | 国产精品久久久久久久久免费高清 | 女人夜夜春 | 国产99久久精品 | 日韩免费一区二区 | 亚洲专区欧美 | 精品www| 天天久| 一级性大片| 欧美一级在线免费观看 | 欧美性一区二区三区 | 一区二区不卡视频在线观看 | 亚洲天堂一区 | 国产精品不卡视频 | 奇米影视四色777me | 欧美在线一区二区三区 | 中文字幕一区二区三区在线视频 | 色婷婷激情 | 国产中文在线 | 国产欧美日韩综合精品一区二区 | 日本视频免费高清一本18 | 精品久久精品久久 | 日韩精品视频在线观看免费 | 黄色一级片黄色一级片 | 亚洲激情av | 欧美激情精品久久久久 | 日日操综合 | 日韩一区二区在线观看 | 人人草人人 | 一区在线观看视频 | 国产97免费视频 | 日韩视频免费在线播放 | 婷婷国产在线观看 | 一区二区在线免费观看 | 亚洲欧美日韩电影 | 精品一区二区三区四区五区 | 青青草久久 | 成人国产精品久久久 | 午夜黄色影院 | av在线免费播放 | 国产日韩一区二区 | 日本黄色大片免费观看 | 91亚洲国产精品 | 成人亚洲欧美 | 精品久久久久久久久久久久久 | 久久成人免费观看 | 91久久| 精品二三区| 黄色片免费看 | 久久久久久网站 | 色资源站 | 免费毛片网 | 精品人人 | 久久久999国产 | 中文字幕在线免费 | 亚洲福利二区 | 香蕉久久久久久 | 国产成人精品一区二区三区视频 | 日本欧美在线 | 在线观看日韩精品 | 国产大胆自拍 | 久草免费在线 | 日韩视频在线免费播放 | 亚洲成人网络 | a久久 | 色天天久久 | 成人a在线观看 | 日韩精品一区二区三区在线 | 欧美一区二区在线免费观看 | 久久久久久久久久久久福利 | 亚洲精品一区二区三区99 | 欧美性网 | 男女免费在线观看 | 国产无区一区二区三麻豆 | 99re6热在线精品视频播放 | 99爱免费观看 | 国产一区二区三区在线 | 国产一级片免费观看 | 国产做a爰片久久毛片a我的朋友 | 中文字幕日韩欧美一区二区三区 | 国产一区二区三区四区 | 亚洲中午字幕在线观看 | 久久综合久久久 | 看黄网址 | 欧洲美女7788成人免费视频 | 久久性| 欧美一区二区精品 | 在线观看三区 | 日韩一区二区三区在线 | 日韩成人在线播放 | 99久久99 | 91精品国产欧美一区二区成人 | 91精品国产aⅴ | 精品国产31久久久久久 | 在线视频 中文字幕 | 免费观看毛片 | 日日骚视频 | 伊人免费在线观看高清版 | 2019天天干夜夜操 | 伊人色综合久久久天天蜜桃 | 青青草一区 | 精品一区二区三 | 国产免费av网站 | 亚洲成人av在线 | 亚洲精品乱码久久久久久花季 | 仙人掌旅馆在线观看 | 国产精品日本一区二区不卡视频 | 精品视频久久 | 亚洲男人天堂网 | 国产精品国产精品 | 青青草国产成人av片免费 | 久久se精品一区精品二区 | 天天操免费 | 在线视频 中文字幕 | 六月丁香av | 久久激情网站 | 超碰最新在线 | 日韩国产在线观看 | 久久99国产精品久久99大师 | 在线观看第一页 | 免费激情小视频 | 99re在线视频 | 免费观看日韩一级片 | 国产精品久久久久久久午夜片 | 一级黄色片欧美 | a√免费视频 | 欧美二三区 |