精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

用 LangChain4j+Ollama 打造 Text-to-SQL AI Agent,數據庫想問就問

人工智能
如今用 Java 在本地折騰大語言模型其實特簡單。輕量級模型加上用熟悉的語言寫的結構清晰的代碼,讓這些想法快速原型化又快又好玩!

想象一下:老板拿著 Excel 表問你 “咱們家最暢銷的三款產品是啥?”,你卻對著復雜的 SQL 查詢語句抓頭發(fā) —— 這種尷尬場面,以后有 AI 幫忙就再也不會出現啦!

其實很多職場人(甚至有些開發(fā))都搞不定 SQL,更別說非技術出身的管理者了。要是能直接用大白話問數據庫問題,比如 “誰買的東西最多?”“哪個產品最賺錢?”,那工作效率不得直接起飛?

先給大家看個實際效果:

問題:咱們最暢銷的三款產品是啥?

AI 給出的答案:根據數據庫數據,top3 暢銷產品是:

筆記本電腦 —— 賣了 3 臺

鼠標 —— 賣了 2 臺

鍵盤 —— 賣了 2 臺

這三款產品的銷量都在 2 臺以上,是目前的銷量冠軍。

不過先說明哈:這方法不算 “最優(yōu)解”,主要是帶大家玩一玩,感受下 LLM(大語言模型)的能力。畢竟先摸清 AI 的 “脾氣”,才能解鎖更多騷操作嘛~(要是真要上生產環(huán)境,還是得用 MCP 或者 Langchain4j 的 @Tool 工具調用功能,專業(yè)的事得靠專業(yè)工具!)

1.核心思路:讓 AI 當你的 “SQL 翻譯官”

整個流程其實超簡單,就像 “傳話游戲”,只不過中間多了個 AI 幫忙:

你用大白話提問題(比如 “最暢銷的產品是啥?”)

給 Ollama 模型(一款本地能跑的 AI)看數據庫的 “結構說明書”,讓它生成對應的 SQL 查詢語句

用這個 SQL 去數據庫里撈數據

再把撈到的數據和你的問題一起丟給 AI,讓它給你一個人話版答案

全程沒什么 “黑科技”,就是靠 AI 幫你搞定 “把大白話轉成 SQL” 和 “把數據轉成人話” 這兩步,咱們純屬邊玩邊學~

2.準備工作:先搭好 “工具箱”

在寫代碼之前,得先把需要的工具準備好,就像做飯前要先買菜一樣:

  • 本地起個 PostgreSQL 數據庫(用 Docker 超方便)

復制下面這行命令,在終端里敲一下,就能自動下載并啟動數據庫,連安裝步驟都省了:

docker run --name tts-db \
 -e POSTGRES_USER=tts-user \
 -e POSTGRES_PASSWORD=tts-pass \
 -e POSTGRES_DB=tts-db \
 -p 5432:5432 -d postgres

給大家劃重點:

數據庫名:tts-db

用戶名:tts-user

密碼:tts-pass

記好這三個信息,后面要用到!

  • 裝 Ollama(本地跑 AI 模型的工具)

直接去官網下載:https://ollama.com/download,跟裝微信一樣簡單。

裝完后,在終端里敲一句

ollama run llama3.2:1b

就能啟動目前最小的 Ollama 模型(才 1.3GB)。雖然這模型不算 “聰明”,但勝在跑得快,練手剛好合適~ 后面想換厲害的模型,直接換個命令就行(官網有各種免費模型可選)。

  • 建個 Java 項目(用 Gradle 舉例)

先建個普通的 Java Gradle/Maven 項目,然后在build.gradle里加三個依賴(相當于給項目裝 “插件”):

implementation 'org.postgresql:postgresql:42.7.7'
implementation 'dev.langchain4j:langchain4j:1.0.1'
implementation 'dev.langchain4j:langchain4j-ollama:1.0.1-beta6'

3.動手實操:一步步搭起 “AI 查數據庫” 功能

準備工作做完,就到最有意思的環(huán)節(jié)了!咱們一步步來,別怕,代碼都給你寫好了~

第一步:給數據庫填點 “測試數據”

先建個init.sql文件(放在src/main/resources文件夾下),里面寫好建表和插數據的 SQL。我讓 ChatGPT 幫我編了個簡化的電商數據庫,大家直接用就行:

-- 先刪舊表,避免重復
DROP TABLE IF EXISTS orders;
DROP TABLE IF EXISTS products;
DROP TABLE IF EXISTS customers;
-- 顧客表
CREATE TABLE customers (
    id INT PRIMARY KEY,
    name VARCHAR(100),  -- 姓名
    email VARCHAR(100), -- 郵箱
    city VARCHAR(50)    -- 城市
);
-- 產品表
CREATE TABLE products (
    id INT PRIMARY KEY,
    name VARCHAR(100),  -- 產品名
    price DECIMAL(8,2)  -- 價格
);
-- 訂單表(記錄誰買了啥)
CREATE TABLE orders (
    id INT PRIMARY KEY,
    customer_id INT,    -- 關聯(lián)顧客表
    product_id INT,     -- 關聯(lián)產品表
    quantity INT,       -- 購買數量
    order_date DATE,    -- 下單日期
    FOREIGN KEY (customer_id) REFERENCES customers(id),
    FOREIGN KEY (product_id) REFERENCES products(id)
);
-- 插點測試顧客
INSERT INTO customers VALUES
(1, '張三', 'zhangsan@email.com', '北京'),
(2, '李四', 'lisi@email.com', '上海'),
(3, '王五', 'wangwu@email.com', '廣州'),
(4, '趙六', 'zhaoliu@email.com', '深圳'),
(5, '錢七', 'qianqi@email.com', '杭州');
-- 插點測試產品
INSERT INTO products VALUES
(1, '筆記本電腦', 9999.99),
(2, '鼠標', 99.99),
(3, '鍵盤', 299.99),
(4, '顯示器', 1999.99),
(5, '耳機', 799.99);
-- 插點測試訂單
INSERT INTO orders VALUES
(1, 1, 1, 1, '2024-01-15'),  -- 張三買1臺筆記本
(2, 2, 2, 2, '2024-01-16'),  -- 李四買2個鼠標
(3, 1, 3, 1, '2024-01-17'),  -- 張三買1個鍵盤
(4, 3, 1, 1, '2024-01-18'),  -- 王五買1臺筆記本
(5, 4, 4, 1, '2024-01-19'),  -- 趙六買1個顯示器
(6, 2, 5, 1, '2024-01-20'),  -- 李四買1個耳機
(7, 5, 2, 3, '2024-01-21'),  -- 錢七買3個鼠標
(8, 1, 4, 1, '2024-01-22'),  -- 張三買1個顯示器
(9, 3, 3, 1, '2024-01-23'),  -- 王五買1個鍵盤
(10, 4, 2, 1, '2024-01-24'); -- 趙六買1個鼠標

有了這些數據,就能問 “誰買的鼠標最多?”“筆記本賣了多少臺” 這類問題啦~

第二步:寫個 “數據庫管理器”(幫你連數據庫 + 初始化數據)

建個DatabaseManager類,負責兩件事:連數據庫,以及執(zhí)行上面的init.sql文件初始化數據。代碼里都加了注釋,看不懂的地方看注釋就行:

package com.tsvetkov.db;


import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;


public class DatabaseManager {
    // 數據庫連接信息(就是之前讓你記的那三個!)
    private static final String URL = "jdbc:postgresql://localhost:5432/tts-db";
    private static final String USER = "tts-user";
    private static final String PASSWORD = "tts-pass";


    // 連數據庫并初始化表和數據
    public static Connection getInitialConnection() throws SQLException, IOException {
        // 1. 連數據庫
        Connection connection = DriverManager.getConnection(URL, USER, PASSWORD);
        System.out.println("成功連到PostgreSQL啦!");


        // 2. 讀init.sql文件,執(zhí)行里面的SQL
        return new String(Files.readAllBytes(Paths.get("src/main/resources/init.sql")));
    }

第三步:初始化 AI 助手(讓 Ollama 模型跑起來)

建個AIUtils類,負責啟動 Ollama 模型,相當于給你找個 “AI 小助手”:

import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.ollama.OllamaChatModel;
import dev.langchain4j.service.AiServices;
public class AIUtils {
    // 生成AI助手(能幫你轉SQL、寫答案)
    public static AIAssistant getAIAssistant() {
        return AiServices.builder(AIAssistant.class)
                .chatModel(initOllamaChatModel()) // 連Ollama模型
                .build();
    }
    // 啟動Ollama的llama3.2:1b模型
    private static ChatModel initOllamaChatModel() {
        return OllamaChatModel.builder()
                .baseUrl("http://localhost:11434") // Ollama默認地址
                .modelName("llama3.2:1b") // 用的模型名
                .build();
    }
}

第四步:定義 AI 助手的 “能力”(讓它知道該干啥)

建個AIAssistant接口,用注解告訴 AI:“你要幫我把大白話轉成 SQL”“你要幫我把數據轉成人話”。這就像給 AI 發(fā) “任務清單”:

import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.V;
public interface AIAssistant {
    @UserMessage("""
      You are a senior SQL engineer. Given the database schema and user question below, write a syntactically correct and schema-valid SQL SELECT query.
      Database Schema (Use only columns and tables listed here)
      {{schemaDescription}}
      Rules:
      Only valid syntax queries - meaning it must start with SELECT
      Only use tables and columns from the schema above — do not guess
      Only use SELECT statements (no INSERT, UPDATE, DELETE)
      Use explicit JOINs, not subqueries unless necessary
      Add LIMIT 100 to large result sets if not specified in the question
      Use aggregate functions (COUNT, SUM, etc.) only if the question requires it
      Return only the SQL query, no explanation, no comments
      The query must be valid SQL and executable without syntax errors
      User Question
      {{question}}
    """)
    String getQuery(@V("question") String question,  @V("schema") String schemaDescription);
}

第五步:寫個 “數據庫結構分析器”(給 AI 看 “說明書”)

AI 得知道數據庫里有哪些表、每個表有哪些字段,才能寫出正確的 SQL。所以建個SchemaAnalyzer類,把數據庫結構整理成 AI 能看懂的格式(還會加幾條測試數據當例子):

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
// 存字段信息(字段名+字段類型)
record ColumnInfo(String name, String type) {}
public class SchemaAnalyzer {
    // 每個表只取3條數據當例子,太多了AI看不過來
    private static final int EXAMPLES_LIMIT = 3;
    // 生成數據庫結構描述(給AI看的“說明書”)
    public static String getSchemaDescription(Connection connection) throws SQLException {
        if (connection == null) {
            throw new IllegalArgumentException("數據庫沒連上,別瞎傳!");
        }
        StringBuilder schemaDesc = new StringBuilder();
        // 1. 先獲取所有表名
        List<String> tables = getTables(connection);
        // 2. 逐個表整理結構和示例數據
        for (String table : tables) {
            schemaDesc.append("表名:").append(table).append("\n");
            schemaDesc.append(getTableDetail(connection, table));
        }
        return schemaDesc.toString();
    }
    // 整理單個表的結構(字段名+類型)和示例數據
    private static String getTableDetail(Connection connection, String table) throws SQLException {
        StringBuilder detail = new StringBuilder();
        // 獲取表的所有字段
        List<ColumnInfo> columns = getColumns(connection, table);
        for (ColumnInfo col : columns) {
            detail.append("  - ").append(col.name()).append("(類型:").append(col.type()).append(")\n");
        }
        // 獲取表的示例數據
        List<List<String>> sampleRows = getSampleRows(connection, table, columns);
        // 把示例數據寫成表格格式,AI看得更清楚
        detail.append("示例數據:\n");
        detail.append("  | ");
        for (ColumnInfo col : columns) {
            detail.append(col.name()).append(" | ");
        }
        detail.append("\n");
        for (List<String> row : sampleRows) {
            detail.append("  | ");
            for (String value : row) {
                detail.append(value).append(" | ");
            }
            detail.append("\n");
        }
        return detail.toString();
    }
    // 獲取數據庫里的所有表名
    private static List<String> getTables(Connection connection) throws SQLException {
        List<String> tables = new ArrayList<>();
        try (ResultSet rs = connection.getMetaData().getTables(null, "public", "%", new String[]{"TABLE"})) {
            while (rs.next()) {
                tables.add(rs.getString("TABLE_NAME"));
            }
        }
        return tables;
    }
    // 獲取單個表的所有字段
    private static List<ColumnInfo> getColumns(Connection connection, String table) throws SQLException {
        List<ColumnInfo> columns = new ArrayList<>();
        try (ResultSet rs = connection.getMetaData().getColumns(null, "public", table, "%")) {
            while (rs.next()) {
                columns.add(new ColumnInfo(
                        rs.getString("COLUMN_NAME"),  // 字段名
                        rs.getString("TYPE_NAME")     // 字段類型
                ));
            }
        }
        return columns;
}        
   private static List<List<String>> getSampleRows(Connection connection, String table, List<ColumnInfo> columns) throws SQLException {
        var rows = new ArrayList<List<String>>();
        try (ResultSet rs = connection.createStatement().executeQuery("SELECT * FROM \"" + table + "\" LIMIT " + EXAMPLES_LIMIT)) {
            while (rs.next()) {
                var row = new ArrayList<String>();
                for (ColumnInfo col : columns) {
                    row.add(rs.getString(col.name()));
                }
                rows.add(row);
            }
        }
        return rows;
    }
 }

咱們的操作邏輯其實特簡單:先搞清楚數據庫里有哪些表,每張表有啥字段、字段是啥類型,然后按照剛才說的格式生成描述,再從每張表里挑幾條數據當例子 —— 齊活!

舉個例子,要是調用 AIAssistant 的 getQuery 方法,問 “產品目錄里最貴的是啥?”,AI 可能會返回這樣的 SQL:

SELECT T1.price FROM products AS T1 INNER JOIN orders AS T2 ON T1.id= T2.product_id GROUP BY T1.price ORDER BY SUM(T1.price) DESC LIMIT 1
執(zhí)行數據庫查詢

下一步就是執(zhí)行這個查詢,把結果撈出來。咱先簡單校驗下 SQL 語法,不用搞太復雜的操作。給 DatabaseManager 類加個 validateQuery 方法就行:

public static void validateQuery(String sql) {
    // 基礎校驗——只允許SELECT語句
    String upperSql = sql.toUpperCase().trim();
    if(!upperSql.startsWith("SELECT") ||
            upperSql.contains("DROP") ||  // 不準刪表
            upperSql.contains("DELETE") || // 不準刪數據
            upperSql.contains("INSERT") || // 不準插數據
            upperSql.contains("UPDATE") || // 不準改數據
            upperSql.contains("ALTER") ||  // 不準改表結構
            upperSql.contains("CREATE")) { // 不準建表
        throw new RuntimeException("SQL有問題,不能執(zhí)行:\n"+sql);
    }
}

校驗通過后,就可以執(zhí)行查詢,然后把結果整理一下。

比如問 “能列出所有產品和它們的價格不?”

模型可能會返回這樣的查詢:

SELECT p.name, p.price FROM products p ORDER BY p.price LIMIT 100

我希望結果能長成這樣:

name       | price
Mouse      | 25.99
Keyboard   | 75.99
Headphones | 149.99
Monitor    | 299.99
Laptop     | 999.99

咱們來實現個方法干這事兒。這個方法接收模型生成的 SQL 查詢和數據庫連接作為參數,就叫 getFormattedResultsFromQuery:

private static String getFormattedResultsFromQuery(Connection conn, String sql) throws SQLException {
    DatabaseManager.validateQuery(sql);
    var resultsDescription = new StringBuilder();
    try (Statement stmt = conn.createStatement();
         ResultSet rs = stmt.executeQuery(sql)) {
        int columnCount = rs.getMetaData().getColumnCount();
        // 先拼表頭
        for (int i = 1; i <= columnCount; i++) {
            resultsDescription.append(rs.getMetaData().getColumnName(i));
            if (i < columnCount) resultsDescription.append(" | ");
        }
        resultsDescription.append("\n");
        // 再拼數據行
        while (rs.next()) {
            for (int i = 1; i <= columnCount; i++) {
                resultsDescription.append(rs.getString(i));
                if (i < columnCount) resultsDescription.append(" | ");
            }
            resultsDescription.append("\n");
        }
    }
    return resultsDescription.toString();
}
用 SQL 查詢結果生成最終答案

現在可以給模型定義個模板,把數據庫結構、查詢結果和用戶的問題一起傳過去 —— 這樣模型應該就能給出靠譜的答案了。給 AIAssistant 類加個這玩意兒:

@UserMessage("""
      You are a data analyst. Based on the database schema, the user’s question, the SQL query and the SQL query results, generate a clear, concise, human-readable answer.
      Focus on answering the user's question directly using the data provided — do not describe the SQL or repeat the table structure. Give a straight answer.
      ### Database Schema
      {{schema}}
      ### User Question
      {{question}}
      ### SQL Query
      {{ query }}
      ### SQL Query Results
      {{results}}
      ### Answer
    """)
    String explainAnswer(@V("question") String question, @V("schema") String schema, @V("results") String results);

搞定啦!咱來捋一捋:

  1. 用戶提個問題
  2. 生成數據庫結構描述
  3. 把問題和結構描述傳給模型
  4. 模型生成能回答用戶問題的 SQL 查詢
  5. 校驗查詢
  6. 執(zhí)行查詢
  7. 整理結果
  8. 把結果、數據庫結構和用戶問題傳給模型
  9. 得到人話版答案

咱們把這些零件組裝到一個簡單的 main 方法里:

public static void main(String[] args) throws SQLException, IOException {
        System.out.println("Starting our text-to-sql application...");
        AIAssistant aiAssistant = AIUtils.getAIAssistant();
        try (Connection conn = DatabaseManager.getInitialConnection()) {
            String schemaDescription = SchemaAnalyzer.getSchemaDescription(conn);
            String question = "What are our top 3 most ordered products?";
            String query = aiAssistant.getQuery(question, schemaDescription);
            String formattedQueryResults = getFormattedResultsFromQuery(conn, query);
            String humanAnswer = aiAssistant.explainAnswer(question, schemaDescription, query, formattedQueryResults);
            System.out.println(humanAnswer);
        }
}

最后,運行這個例子,會得到類似這樣的結果:

啟動咱們的文本轉SQL應用...
成功連到PostgreSQL啦!
數據庫表和數據都初始化好咯~
張三總共下了3單。

得說明一下,用我這個例子里的模型,結果不一定總能完美無缺。不過用來瞎折騰折騰夠夠的了,而且試試不同的模型模板,看啥樣能讓模型給出更好的答案,還挺有意思的。要是用更厲害的模型,幾乎每次都能得到不錯的結果。

你可能還會發(fā)現,模型生成的查詢經常有問題,所以整個重試邏輯是個不錯的練習。玩得開心就好!

總結

如今用 Java 在本地折騰大語言模型其實特簡單。輕量級模型加上用熟悉的語言寫的結構清晰的代碼,讓這些想法快速原型化又快又好玩!就像文章開頭說的,這個方法不算優(yōu)化,也不適合實際生產應用,但它基于 AI 代理的理念,簡化展示了底層的工作原理。

如果需要直接用Text-To-SQL的框架請移步我們開源的基于Spring AI實現的Java的Text-To-SQL框架SuperSQL

責任編輯:武曉燕 來源: HELLO程序員
相關推薦

2025-05-07 01:01:00

JavaQuarkusAI

2024-08-01 13:12:57

2025-03-31 00:44:00

JavaAI開發(fā)

2025-10-24 10:58:24

智能體大語言模型LLM

2025-10-10 09:03:18

2025-04-22 03:00:00

模型SpringAI

2017-07-28 15:12:28

Neo4j圖數據庫

2025-05-22 02:00:00

AI人工智能前端

2024-08-02 08:00:00

2025-03-11 00:25:00

組件接口工具

2010-06-30 08:27:45

SQL Server數

2023-06-06 14:16:06

ChatGPTAI

2024-12-13 08:32:28

向量數據庫云原生LangChain

2025-05-07 08:14:58

2010-05-05 11:17:55

Oracle數據庫

2025-01-14 10:29:34

2023-10-12 08:59:52

Docker AI生成式 AI

2011-07-26 12:48:52

neo4j圖數據庫

2016-03-17 21:35:48

2010-05-14 14:12:58

MySQL數據庫優(yōu)化
點贊
收藏

51CTO技術棧公眾號

自拍亚洲一区欧美另类| 精品久久久久久国产91| 亚洲a∨日韩av高清在线观看| 蜜桃av免费在线观看| 日韩中文一区二区| 精品色蜜蜜精品视频在线观看| 奇米精品在线| 国产成人麻豆精品午夜在线| 国产精品日韩| 精品国产美女在线| 亚洲男女在线观看| 欧美一级网址| 欧美日韩午夜剧场| 日韩人妻精品一区二区三区| 日韩精品视频无播放器在线看 | 精品无码一区二区三区在线| 国产免费a∨片在线观看不卡| 国产中文字幕一区| 欧洲精品毛片网站| 日韩精品欧美在线| 国产精品久久婷婷| 国产日韩1区| 久久躁狠狠躁夜夜爽| 最新中文字幕视频| 一区二区亚洲视频| 欧美日韩一区二区三区不卡 | 国产欧美日韩一级| xxx欧美精品| 免费观看av网站| 三级欧美日韩| 欧美人妖巨大在线| 88av.com| 天堂中文在线播放| 亚洲自拍偷拍麻豆| 中文字幕免费在线不卡| 黄色毛片在线观看| 99久免费精品视频在线观看| 亚洲已满18点击进入在线看片| 香蕉污视频在线观看| 在线成人国产| 久久99精品久久久久久青青91| 天天干天天操天天拍| 精品一区免费| 亚洲精品久久久久中文字幕二区| 中文字幕乱码在线人视频| 激情久久99| 在线观看一区日韩| 国产成人手机视频| 日韩免费电影| 色综合婷婷久久| 男人天堂1024| 色多多在线观看| 午夜影视日本亚洲欧洲精品| 天天综合五月天| 免费av不卡| 国产精品进线69影院| 天天综合色天天综合色hd| 福利在线观看| 国产精品污www在线观看| 欧美中文娱乐网| 黄色影院在线播放| 国产午夜精品福利| 日本视频精品一区| а天堂8中文最新版在线官网| 91一区二区在线| 免费日韩av电影| 日色在线视频| 91麻豆123| 欧美污视频久久久| 成年人视频免费在线观看| 国产精品午夜免费| 在线不卡日本| 青青草原国产在线| 亚洲成人精品一区二区| 啊啊啊一区二区| 午夜av成人| 欧美精品高清视频| 美女又黄又免费的视频| 欧美高清视频看片在线观看| 亚洲女成人图区| 国产7777777| 中出一区二区| 26uuu另类亚洲欧美日本一| 亚洲图片在线视频| 久久精品国产亚洲a| 亚洲自拍中文字幕| 亚欧在线观看视频| 日本一区二区三级电影在线观看| 亚洲精品自在在线观看| 国产精品无码天天爽视频| 国产一区二区剧情av在线| 成人情视频高清免费观看电影| 天天干天天干天天干| 久久久久久久久免费| 最新欧美日韩亚洲| 国产盗摄——sm在线视频| 色哟哟精品一区| 亚洲一级片av| 欧美调教在线| 久久精品欧美视频| 亚洲天堂一区在线| 久草精品在线观看| 激情小说网站亚洲综合网 | 中文日韩在线观看| 欧美高清视频一区二区三区| 先锋影音久久久| 92国产精品久久久久首页| 神马精品久久| 亚洲另类在线一区| 精品少妇无遮挡毛片| 日韩中文字幕无砖| 中文字幕亚洲综合久久| 日韩精品一卡二卡| 精品一区二区免费看| 久久香蕉综合色| av激情在线| 欧美亚洲自拍偷拍| 免费的av网站| 亚洲欧美伊人| 国产精品免费一区二区三区都可以| 性一交一乱一透一a级| 欧美激情一区二区| 欧美 日韩 亚洲 一区| 欧美电影院免费观看| 亚洲香蕉伊综合在人在线视看| 国产一级在线免费观看| 国产一区二区三区免费| 少妇特黄a一区二区三区| 日本а中文在线天堂| 欧美xingq一区二区| 国产又粗又猛又爽又黄的视频四季 | 日韩精品无码一区二区三区| 人人草在线视频| 亚洲成人av中文字幕| 久久久久亚洲av片无码| 日本亚洲视频在线| 日韩wuma| 日韩电影免费观看高清完整版| 亚洲黄色在线观看| 久久综合综合久久| 国产一区二区三区蝌蚪| 在线观看欧美一区| 成人国产综合| 中文字幕国产精品| 日韩人妻精品中文字幕| 99re热视频这里只精品| 欧美图片激情小说| 99这里只有精品视频| 欧美精品18videosex性欧美| av中文字幕免费在线观看| 中文字幕一区二区三| 视频二区在线播放| 日韩久久精品| 成人福利免费观看| 国产激情视频在线观看| 欧美一级二级在线观看| 免费又黄又爽又色的视频| 国产麻豆精品在线观看| 99久热在线精品视频| 综合视频一区| 久久久在线视频| 手机看片1024国产| 欧美性猛交99久久久久99按摩| 亚洲狠狠婷婷综合久久久久图片| 国产欧美69| 日韩亚洲不卡在线| 农村妇女一区二区| 欧美成年人视频网站| 亚洲第一视频在线播放| 亚洲成av人片| 无码国产69精品久久久久同性| 老司机午夜精品视频| 亚洲欧洲精品一区二区| 国产aa精品| 九九精品在线视频| 污污网站在线免费观看| 日韩欧美在线第一页| 极品尤物一区二区| 国产一区不卡在线| 成人午夜视频在线观看免费| 精品在线手机视频| 成人a在线视频| 欧美午夜大胆人体| 亚洲人a成www在线影院| 国产精品久久久久久久免费| 亚洲一区二区三区四区在线| 中文字幕5566| 久久激情五月婷婷| 国产免费一区二区视频| 国产一区二区在线| 97久草视频| 欧美男体视频| 欧美俄罗斯乱妇| 欧美挠脚心网站| 8x8x8国产精品| 日韩三级视频在线播放| 欧美激情一区在线观看| 亚洲精品成人无码毛片| 日韩国产精品久久久| 狠狠噜天天噜日日噜| 精品国产网站| 豆国产97在线| 99久久精品一区二区成人| 久久久噜噜噜久久久| 在线国产情侣| 精品香蕉一区二区三区| 国产免费久久久| 91久久久免费一区二区| 精品99久久久久成人网站免费| 久久看人人爽人人| www.欧美com| 另类的小说在线视频另类成人小视频在线 | 91av在线免费观看| 国产原创精品视频| 国产一区二区三区视频在线观看| 精品人妻一区二区三区换脸明星 | 久久久久久久久久久av| 不卡在线视频| 亚洲精品视频播放| 国精产品一品二品国精品69xx| 欧美三级在线视频| 一级片视频在线观看| 亚洲综合一区二区| 日韩在线不卡av| 久久精品亚洲精品国产欧美kt∨ | 日本一区二区免费在线| 在线观看国产免费视频| 国产一区二区中文字幕| 久久撸在线视频| 日日夜夜免费精品| a在线视频观看| 激情欧美一区二区三区| 国产经典久久久| 91精品一区国产高清在线gif| 日韩精品福利视频| 久久99性xxx老妇胖精品| 操人视频欧美| 亚洲综合网站| 99在线看视频| 欧美日本三级| 亚洲最大av网| 精品一区视频| 亚洲综合社区网| 无码国模国产在线观看| 97超级在线观看免费高清完整版电视剧| 伊人亚洲精品| 成人在线播放av| 91成人小视频| 国产精品久久久久久久久影视| 欧美与亚洲与日本直播| 国产精品久久久久久久久免费看| 欧美国产日韩电影| 国产精品视频自拍| 日韩美女在线| 91嫩草在线视频| 无码国模国产在线观看| 成人免费看片网站| 国产精品白丝一区二区三区| 精品国产一区二区三区麻豆小说| 日韩精品丝袜美腿| 欧美福利精品| 日本成人小视频| 亚洲日本精品一区| 欧美黄在线观看| 水蜜桃色314在线观看| 在线视频精品| 男人透女人免费视频| 蜜桃视频一区二区三区在线观看| 激情黄色小视频| 国产精品亚洲第一区在线暖暖韩国| 国产精久久久久| 99精品桃花视频在线观看| 国产精品无码午夜福利| 亚洲国产成人自拍| 波多野结衣亚洲一区二区| 亚洲一区二区视频在线观看| 国产综合精品视频| 欧美怡红院视频| 精品人妻av一区二区三区| 亚洲高清色综合| 国产精品无码2021在线观看| 久久精品免费电影| 国产三级电影在线播放| 国产精品jvid在线观看蜜臀 | 欧美一区二区美女| 日韩中文字幕影院| 一区二区欧美日韩视频| 伊人精品影院| 热re91久久精品国99热蜜臀| 未满十八勿进黄网站一区不卡| av一区二区在线看| 九九综合九九| 91国在线高清视频| 日韩av一级片| 亚洲一区二区三区黄色| 免费在线亚洲欧美| 中文字幕 欧美日韩| av在线免费不卡| 91导航在线观看| 亚洲成av人**亚洲成av**| 亚洲一二区视频| 亚洲第一福利网| 日本精品在线| 日产日韩在线亚洲欧美 | 国新精品乱码一区二区三区18| 国产一区99| 九色自拍视频在线观看| 精品一区二区影视| av女人的天堂| 性做久久久久久久久| 91麻豆国产视频| 亚洲欧美成人网| 激情影院在线| 成人福利网站在线观看11| 西野翔中文久久精品字幕| 国产日产欧美一区二区| 日韩电影在线一区二区| 亚洲图片综合网| 有坂深雪av一区二区精品| 国产美女www爽爽爽| 亚洲精品久久久久久久久久久久 | 97成人精品视频在线观看| crdy在线观看欧美| 午夜精品一区二区在线观看| 国产美女精品| 亚洲乱妇老熟女爽到高潮的片| 国产精品不卡在线| 亚洲男人天堂网址| 亚洲欧美在线免费观看| 高清精品在线| 97视频中文字幕| 欧美一区二区三区另类 | 成人三级在线视频| 日韩欧美中文字幕视频| 欧美美女一区二区| 在线观看a视频| 国产三级精品网站| 日韩一区二区在线免费| 亚洲精品视频导航| 国产拍欧美日韩视频二区| 在线永久看片免费的视频| 亚洲精品动漫久久久久| 国产乱妇乱子在线播视频播放网站| 亚洲综合在线小说| 欧美va天堂在线| 潘金莲一级淫片aaaaa| 亚洲美女视频一区| 国产福利资源在线| 欧美日韩福利视频| 91在线一区| 国产深夜男女无套内射| 不卡的电视剧免费网站有什么| 久久精品国产亚洲AV无码麻豆 | 亚洲av成人无码一二三在线观看| 亚洲第一精品在线| 亚洲欧美日韩免费| 日韩av片免费在线观看| 精品一区在线| 午夜免费看视频| 亚洲欧美日韩国产另类专区| 99精品在线看| 久久久久久久色| 日韩a级大片| 污污视频网站免费观看| 中文字幕欧美三区| 国产情侣在线播放| 欧美激情一区二区三区久久久| 久久人人爽人人爽人人片av不| 1024av视频| 中文字幕av一区二区三区免费看| 91成年人视频| 久久久亚洲精选| 国模吧精品视频| 欧美视频亚洲图片| 亚洲成人综合在线| 国产福利在线| 亚洲一区二区三区香蕉| 一本色道久久综合亚洲精品不卡| 谁有免费的黄色网址| 欧美一区二区私人影院日本| 欧美xxxx黑人又粗又长| 美女被啪啪一区二区| 麻豆91在线播放| 精品无码一区二区三区电影桃花| 亚洲男人天堂2024| 久久国产三级| 人妻夜夜添夜夜无码av| 国产日韩欧美一区二区三区乱码| 国产又粗又猛又黄| 国产综合在线看| 成人免费a**址| 在线免费看黄色片| 欧美午夜精品久久久久久超碰 | 国产精品高潮粉嫩av| 综合久久十次| 欧美多人猛交狂配| 日韩亚洲欧美中文三级| 美女福利一区二区三区| 国产精品啪啪啪视频| 久久久久久久国产精品影院|