DBHub — 讓 AI 直接查資料庫的 MCP Server 安裝與使用指南
寫 SQL、跑查詢、複製結果、貼給 AI、等回覆、發現少撈了一個欄位、再跑一次。這個迴圈跑過三輪以上的人,大概都會冒出同一個念頭:讓 AI 自己去查不就好了? DBHub 就是幹這件事的。Bytebase 團隊開源的資料庫 MCP Server,裝上去之後 AI 直接透過 MCP 協定存取資料庫——查結構、跑 SQL 都行,你不用再當中間人搬運資料。 支援的資料庫MSSQL、MySQL、PostgreSQL、MariaDB、SQLite、Oracle,涵蓋範圍比預期廣。安裝走 npx 或 Docker 都行。 安裝方式專案級安裝連線資訊只在當前專案目錄下生效,不會跨專案污染。 MSSQL: 1claude mcp add dbhub --scope project -- npx @bytebase/dbhub --transport stdio --dsn "sqlserver://user:password@host:port/database" MySQL: 1claude mcp add dbhub --scope project -- npx @by...
npx vs npm 差異與 MCP Server 自動更新機制
最近在幫 Claude Code 設定 MCP Server 的時候,用到了 Google 官方出的 chrome-devtools-mcp 這個工具,主要是拿來做瀏覽器的自動化驗證。安裝指令裡用的是 npx 而不是 npm install,一開始我還沒特別在意,但後來仔細研究才發現,這兩者的行為差異其實直接影響到版本更新策略。這邊把我整理的筆記記錄一下。 npm install vs npx 到底差在哪?說實話,剛開始學 Node.js 的時候,我也搞不太清楚 npx 跟 npm 的差別,總覺得都是裝套件用的。但其實它們的設計理念完全不同。 簡單來說,npm install 會把套件下載到 node_modules/ 資料夾裡,持久保存在本地。而 npx 的概念則是「臨時下載、執行完就可以不管了」。 幾個關鍵差異整理一下: 版本解析時機:npm install 安裝時解析一次版本就固定了;npx 加上 @latest 的話,每次執行都會重新解析,自動抓最新版 磁碟空間:npm 裝了就佔空間;npx 用完可能會被快取策略清掉 啟動速度:npm 因為已經在本地了所以快;npx 首...
Java 併發控制 - Semaphore 與 volatile
多執行緒環境下控制共享資源的訪問,是每個 Java 工程師必會的技能。Semaphore 控制許可數量,volatile 確保可見性。這兩個概念常常被搞混,今天一次說清楚。 Semaphore 基本概念Semaphore 就是「信號量」,用來控制同時訪問某個資源的執行緒數量。 實時比喻停車場有 10 個停車位。每個進來的車要先拿個 ticket(acquire 許可),停好了才能放 ticket(release 許可)。只有拿到 ticket 的車才能進。 123Semaphore(10) = 10 個停車位車進來:semaphore.acquire() // 許可數 -1車停好:semaphore.release() // 許可數 +1 基本用法123456789101112131415import java.util.concurrent.Semaphore;// 建立 Semaphore,許可數 = 5Semaphore semaphore = new Semaphore(5);public void accessResource() throws Interrupt...
Java 集合操作 - List 差集與 Stream 分割 JsonArray
集合操作是日常編程的基礎,但很多人寫得很醜。本篇涵蓋三個常見的集合操作場景:List 差集、JsonArray 分割成 List,以及 Stream 查詢計數。這些小技巧能讓代碼更簡潔。 1. List 差集需求:從 list1 移除所有在 list2 裡出現的元素。 簡單但爛的做法1234567891011121314151617List<String> list1 = Arrays.asList("Apple", "Banana", "Cherry", "Orange");List<String> list2 = Arrays.asList("Banana", "Orange");// 爛做法 1:逐個刪(在迴圈中修改 list,會爆 ConcurrentModificationException)for (String item : list1) { if (list2.contains(item)) { ...
Java 8 時間 API 與 LinkedHashMap 使用筆記
Java 8 的時間 API 用起來比之前的 Date、Calendar 不知道爽幾倍。但新 API 的時區轉換常常爆炸,因為邏輯和以前差很多。LinkedHashMap 是保持插入順序的 Map,常被小看但超實用。一次整理出來。 Java 8 時間 API 基礎主要類123456789101112131415161718192021222324import java.time.*;// LocalDateTime - 純日期時間,沒有時區LocalDateTime now = LocalDateTime.now();System.out.println(now); // 2026-02-20T14:30:45.123456// LocalDate - 只有日期LocalDate today = LocalDate.now();System.out.println(today); // 2026-02-20// LocalTime - 只有時間LocalTime time = LocalTime.now();System.out.println(time); // 14:3...
OkHttp 手動解壓縮 gzip/deflate 響應
大多數時候,OkHttp 會自動解壓 gzip 響應。但某些老舊 server 或特殊場景,response 的 Content-Encoding 是 gzip/deflate,但 OkHttp 沒有自動幫你解。這時就要自己手動解壓。 問題場景通常是這些情況: Server 回傳 Content-Encoding: gzip,但沒有設定好 headers 某些代理或中間層加了壓縮但沒遵循標準 特殊的嵌入式系統的 API 需要在 interceptor 層級處理壓縮和解壓 實作 UnzippingInterceptor直接上完整代碼: 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576import okhttp3.Interceptor;import okhttp3.Response;import okio.BufferedSource...
Jackson JSON 使用技巧 - JsonNode 遍歷與 path()
Jackson 是 Java 裡最強的 JSON 庫,但新手常搞不清楚 JsonNode 的各種遍歷方法,還有 path() 和 get() 的差別。踩過坑以後,整理出來給大家。 JsonNode 遍歷拿到一個 JsonNode,要怎麼遍歷裡面的欄位?有好幾種方法。 方法 1:用 fields() 取得 Iterator12345678910111213141516171819202122232425ObjectMapper mapper = new ObjectMapper();String json = """{ "name": "Alice", "age": 30, "email": "alice@example.com"}""";JsonNode node = mapper.readTree(json);// fields() 回傳 Iterator<Map.Entry&...
Java Stream 操作集錦 - 合併 Map、List 轉 Map、物件排序
Stream 操作是 Java 8+ 的大招。三個最常用的場景:合併多個 Map、把 List 轉成 Map、排序物件。一次整理出來,以後就 copy-paste 吧。 1. Stream 合併多個 Map經常要把好幾個 Map 合起來,最直白的做法是逐個 put: 123456789101112131415Map<String, Integer> map1 = new HashMap<>();map1.put("Apple", 10);map1.put("Banana", 20);Map<String, Integer> map2 = new HashMap<>();map2.put("Orange", 15);map2.put("Pear", 25);Map<String, Integer> map3 = new HashMap<>();map3.put("Cherry", 30);// 爛做法Map<...
Java Stream 過濾 List<JSON> 重複資料
常常拿到一堆 JSON 格式的資料,裡面有一大堆重複的垃圾要清。用 List 直接 remove 重複項,會爆炸。用 Stream 搭配 Collectors,一行代碼搞定,超爽。 問題場景比如從 API 拿到的優惠券列表,user_create_time 相同的算是重複: 123456[ {"id": "C001", "user_create_time": "2026-01-01 10:00:00", "discount": "10%"}, {"id": "C002", "user_create_time": "2026-01-01 10:00:00", "discount": "10%"}, {"id": "C003", "user_c...
淺談 Hash、Hashtable 與 HashMap
Hash 這玩意兒是程式世界的基礎,但一堆人搞不清楚 Hash、Hashtable、HashMap 的差別。常見情況:被問到為啥用 HashMap 不用 Hashtable,只能兩眼發直。今天就一次講清楚。 Hash 的概念Hash 就是把任意長度的資料「打碎」再「拼湊」成固定長度的代碼。 Hash Function 做的事12String input = "This is a very long sentence with lots of words";int hashCode = input.hashCode(); // 回傳一個整數,比如 -123456789 Hash Function 的特性: 決定性 - 同一個輸入永遠產生同一個輸出 單向性 - 不可逆,不能從 hash code 推回原始資料 雪崩效應 - 輸入改一點點,輸出就完全不同 均勻分佈 - 理想情況下,不同輸入的 hash 值均勻分佈在整個範圍 Hash 的應用1. 數位簽章確認資料沒有被竄改。簽署人計算文件的 hash 值,用私鑰加密。驗證人計算一遍 hash,再用公鑰解密比對...














