基于鸿蒙HarmonyOS生态开发远程数据库管理工具核心在于平衡功能强大与系统安全。以下是两种主流技术路线的完整架构与代码实现分别面向通用应用和 PC 专业工具。一、 应用层安全架构基于 HTTP API 中间件推荐此方案遵循“客户端-服务器”模式鸿蒙客户端不直接连接数据库而是通过安全的 HTTPS API 与后端中间件通信。这是最安全、最符合现代应用架构的实践。1. 权限与网络配置首先在module.json5中声明网络访问权限这是应用连接外部服务器的基础。// module.json5 { module: { requestPermissions: [ { name: ohos.permission.INTERNET, reason: 应用需要访问远程数据接口以管理数据库 } ] } }2. 核心数据访问服务类 (ArkTS)封装一个DatabaseService类用于处理所有与后端 API 的 HTTP 通信。此类应运行在独立的 Worker 线程中以避免阻塞 UI。// model/DatabaseService.ets import http from ohos.net.http; import { BusinessError } from kit.BasicServicesKit; // 定义请求数据结构 interface QueryRequest { query: string; parameters?: any[]; } // 定义响应数据结构 interface QueryResponse { code: number; message: string; data: any[]; } export class DatabaseService { private client: http.HttpRequest; private apiBase: string https://api.yourserver.com; // 你的后端API地址 constructor() { this.client http.createHttp(); } /** * 执行远程SQL查询 * param sqlTemplate SQL语句模板 * param params 参数化查询的参数数组防止SQL注入 * returns 查询结果数组 */ async executeQuery(sqlTemplate: string, params: any[] []): Promiseany[] { const url ${this.apiBase}/api/data/query; const requestData: QueryRequest { query: sqlTemplate, parameters: params }; const options: http.HttpRequestOptions { method: http.RequestMethod.POST, header: { Content-Type: application/json, // 可在此处添加认证Token如 Authorization: Bearer ${token} }, extraData: JSON.stringify(requestData), connectTimeout: 15000, // 连接超时15秒 readTimeout: 15000, // 读取超时15秒 }; try { const result await this.client.request(url, options); if (result.responseCode 200) { const responseData: QueryResponse JSON.parse(result.result as string); if (responseData.code 0) { // 假设0为业务成功码 return responseData.data; } else { throw new Error(业务错误: ${responseData.message}); } } else { throw new Error(HTTP错误: ${result.responseCode}); } } catch (err) { const error err as BusinessError; console.error(数据库查询请求失败:, error.code, error.message); throw error; // 抛出错误由调用方处理UI提示 } } /** * 销毁HTTP客户端释放资源 */ destroy() { this.client.destroy(); } }3. 在 Worker 线程中调用服务为避免耗时操作阻塞主线程数据库查询应在 Worker 中执行。// workers/DbWorker.ets import worker from kit.ArkTS; import { DatabaseService } from ../model/DatabaseService; const dbService new DatabaseService(); const workerPort worker.workerPort; // 监听主线程消息 workerPort.onmessage async function(e) { const { id, sql, params } e.data; // id用于关联请求和响应 try { const data await dbService.executeQuery(sql, params); // 查询成功将结果发回主线程 workerPort.postMessage({ id, success: true, data }); } catch (error) { // 查询失败将错误信息发回主线程 workerPort.postMessage({ id, success: false, error: (error as Error).message }); } }4. 在 UI 组件中使用在 ArkUI 组件中创建 Worker 并与之通信更新 UI。// pages/Index.ets import { worker } from kit.ArkTS; Entry Component struct Index { State queryResult: any[] []; State isLoading: boolean false; private dbWorker: worker.ThreadWorker | null null; aboutToAppear() { // 页面出现时创建Worker this.dbWorker new worker.ThreadWorker(workers/DbWorker.ets); this.dbWorker.onmessage (e) { this.isLoading false; const { id, success, data, error } e.data; if (success) { this.queryResult data; } else { // 使用promptAction.showToast提示用户 console.error(查询失败:, error); } }; } aboutToDisappear() { // 页面销毁时终止Worker if (this.dbWorker) { this.dbWorker.terminate(); } } build() { Column() { if (this.isLoading) { LoadingProgress().width(50) } List(this.queryResult) { // ...渲染列表 } Button(查询数据) .onClick(() { this.isLoading true; // 向Worker发送查询任务 this.dbWorker?.postMessage({ id: 1, sql: SELECT * FROM users LIMIT 10, params: [] }); }) } } }二、 PC端特化架构基于 Electron 的桌面数据库工具此方案适用于功能复杂的专业桌面工具利用 Electron 在鸿蒙 PC 上运行 Node.js 环境可直接使用成熟的数据库驱动。1. 架构运行链路Electron 主进程 (main.js)负责创建窗口、管理生命周期并作为 Node.js 运行时加载mysql2或pg等原生驱动。渲染进程 (Renderer)使用 React/Vue 等框架构建 UI通过 Electron 的ipcRenderer与主进程通信。预加载脚本 (preload.js)作为安全桥梁向渲染进程暴露特定的 API。2. 主进程代码 (Node.js)主进程负责建立真实的数据库连接。// main.js (Electron Main Process) const { app, BrowserWindow, ipcMain } require(electron) // 以 PostgreSQL 为例使用 pg 库 const { Client } require(pg) let mainWindow function createWindow () { mainWindow new BrowserWindow({ width: 1200, height: 800, webPreferences: { preload: path.join(__dirname, preload.js) // 预加载脚本 } }) mainWindow.loadFile(index.html) } app.whenReady().then(() { createWindow() }) // 监听来自渲染进程的数据库查询请求 ipcMain.handle(db-query, async (event, config, sql) { const client new Client({ host: config.host, port: config.port, user: config.user, password: config.password, database: config.database, }) try { await client.connect() const res await client.query(sql) return { success: true, data: res.rows } } catch (err) { console.error(err) return { success: false, error: err.message } } finally { await client.end() } })3. 预加载脚本 (安全桥梁)// preload.js const { contextBridge, ipcRenderer } require(electron) contextBridge.exposeInMainWorld(dbAPI, { query: (config, sql) ipcRenderer.invoke(db-query, config, sql) })4. 渲染进程代码 (前端)前端通过暴露的window.dbAPI调用数据库功能。// renderer.ts (在渲染进程中) async function fetchData() { const config { host: your-db-host, port: 5432, user: your-user, password: your-password, database: your-db }; const sql SELECT * FROM users LIMIT 10; const result await (window as any).dbAPI.query(config, sql); if (result.success) { console.log(查询结果:, result.data); // 更新UI } else { console.error(查询失败:, result.error); } }三、 本地数据持久化基于 RelationalStore 的缓存与状态管理当应用处于弱网或离线状态时远程 API 请求会失败。标准的做法是利用鸿蒙内置的关系型数据库RelationalStore作为本地缓存将远程拉取的数据落盘实现“离线可用”的体验。核心代码示例ArkTSimport { relationalStore } from kit.ArkData; import { common } from kit.AbilityKit; export class LocalCacheManager { private rdbStore: relationalStore.RdbStore | undefined undefined; // 1. 初始化本地数据库 async init(context: common.UIAbilityContext) { const config: relationalStore.StoreConfig { name: db_cache.db, securityLevel: relationalStore.SecurityLevel.S1 }; this.rdbStore await relationalStore.getRdbStore(context, config); // 创建本地缓存表 await this.rdbStore.executeSql( CREATE TABLE IF NOT EXISTS USER_CACHE ( ID INTEGER PRIMARY KEY AUTOINCREMENT, USER_ID INTEGER, DATA TEXT, SYNC_TIME INTEGER ) ); } // 2. 将远程拉取的数据写入本地缓存 async saveToCache(userId: number, jsonData: string) { const bucket: relationalStore.ValuesBucket { USER_ID: userId, DATA: jsonData, SYNC_TIME: Date.now() }; await this.rdbStore?.insert(USER_CACHE, bucket); } // 3. 离线状态下读取本地数据 async getFromCache(userId: number): Promisestring | null { const predicates new relationalStore.RdbPredicates(USER_CACHE); predicates.equalTo(USER_ID, userId).orderByDesc(SYNC_TIME).limitAs(1); const resultSet await this.rdbStore?.query(predicates); if (resultSet resultSet.goToNextRow()) { const data resultSet.getString(resultSet.getColumnIndex(DATA)); resultSet.close(); // ️ 关键用完必须关闭 ResultSet 防止连接池耗尽 return data; } resultSet?.close(); return null; } }四、 数据库版本升级平滑迁移与防数据丢失随着业务迭代本地缓存表或应用内置数据库的结构必然发生变化如新增字段。必须通过版本号控制机制执行增量迁移 SQL防止用户升级应用后丢失历史数据。核心代码示例ArkTSasync function upgradeDatabase(store: relationalStore.RdbStore): Promisevoid { const currentVersion store.version; // 从 v1 升级到 v2新增 TAG 字段 if (currentVersion 2) { await store.executeSql(ALTER TABLE USER_CACHE ADD COLUMN TAG TEXT DEFAULT \\); store.version 2; } // 从 v2 升级到 v3为高频查询字段添加索引 if (currentVersion 3) { await store.executeSql(CREATE INDEX IF NOT EXISTS idx_user_id ON USER_CACHE(USER_ID)); store.version 3; } }五、 跨设备一致性分布式数据同步鸿蒙的核心优势在于分布式软总线。对于多端协同的数据库管理工具可利用SyncConfig将本机的数据增量推送到用户的平板或 PC 端实现无缝接续。核心代码示例ArkTSimport { relationalStore } from kit.ArkData; async function syncDataToOtherDevices(store: relationalStore.RdbStore, targetDeviceId: string) { const syncConfig: relationalStore.SyncConfig { mode: relationalStore.SyncMode.SYNC_MODE_PUSH, // 采用推送模式 devices: [targetDeviceId] // 指定目标设备ID }; try { await store.sync(syncConfig); console.info(跨设备数据同步成功); } catch (err) { console.error(同步失败: ${(err as BusinessError).message}); } }六、 数据安全与合规加密存储与手动备份对于包含敏感信息的数据库工具除了网络传输使用 HTTPS本地落盘的数据也必须加密。同时需提供数据库备份能力以防沙箱数据意外损坏。核心代码示例ArkTSexport class SecureDbManager { // 1. 动态更改数据库加密密钥 async changeEncryptionKey(store: relationalStore.RdbStore, newKey: Uint8Array) { try { await store.changeEncryptKey(newKey); console.info(数据库加密密钥已更新); } catch (err) { console.error(更改密钥失败:, (err as BusinessError).message); } } // 2. 将数据库安全备份到应用沙箱的指定目录 async backupDatabase(store: relationalStore.RdbStore, backupPath: string) { try { await store.backup(backupPath); console.info(数据库已成功备份至: ${backupPath}); } catch (err) { console.error(数据库备份失败:, (err as BusinessError).message); } } }七、 现成商业工具Navicat Premium Lite 鸿蒙化对于希望直接使用成熟工具的用户Navicat Premium Lite已完成鸿蒙生态的初步适配是连接和管理多种数据库的便捷选择。多库支持全面兼容 MySQL、PostgreSQL、SQL Server、SQLite、MariaDB 以及国产的 OceanBase、TiDB、PolarDB 等。安全连接支持通过 SSH 隧道和 SSL/TLS 双重加密保障远程访问安全。跨端协同支持连接配置、查询脚本通过 Navicat Cloud 跨设备实时同步。开发者可直接在鸿蒙 PC 应用市场搜索下载无需自行从零构建底层驱动。线程调度 (Critical)鸿蒙规定 UI 操作必须在主线程执行。无论是通过 HTTP 请求还是本地驱动连接数据库查询均属于耗时操作必须在子线程如 Worker中完成随后通过UITaskDispatcher或状态管理切换到主线程更新 UI否则会导致应用无响应ANR。网络安全红线推荐方案采用 API 中间件模式数据库不直接暴露在公网。直连方案不推荐若必须直连远程数据库必须开启 IP 白名单仅允许 App 所在设备的 IP 访问。严禁在客户端代码中硬编码数据库用户名和密码应通过安全的配置文件或系统加密存储读取。异常与超时处理移动网络环境复杂需妥善处理网络断开、连接超时、SQL 语法错误等异常。设置合理的connectTimeout和readTimeout并通过 Toast 等方式友好地提示用户提升 App 稳定性。驱动兼容性不同数据库的 JDBC 驱动类和 URL 格式不同如 MySQL 使用com.mysql.cj.jdbc.Driver在封装底层工具类时需根据实际数据库类型动态调整。
数据库管理工具:连接远程MySQL/PostgreSQL数据库(94)
基于鸿蒙HarmonyOS生态开发远程数据库管理工具核心在于平衡功能强大与系统安全。以下是两种主流技术路线的完整架构与代码实现分别面向通用应用和 PC 专业工具。一、 应用层安全架构基于 HTTP API 中间件推荐此方案遵循“客户端-服务器”模式鸿蒙客户端不直接连接数据库而是通过安全的 HTTPS API 与后端中间件通信。这是最安全、最符合现代应用架构的实践。1. 权限与网络配置首先在module.json5中声明网络访问权限这是应用连接外部服务器的基础。// module.json5 { module: { requestPermissions: [ { name: ohos.permission.INTERNET, reason: 应用需要访问远程数据接口以管理数据库 } ] } }2. 核心数据访问服务类 (ArkTS)封装一个DatabaseService类用于处理所有与后端 API 的 HTTP 通信。此类应运行在独立的 Worker 线程中以避免阻塞 UI。// model/DatabaseService.ets import http from ohos.net.http; import { BusinessError } from kit.BasicServicesKit; // 定义请求数据结构 interface QueryRequest { query: string; parameters?: any[]; } // 定义响应数据结构 interface QueryResponse { code: number; message: string; data: any[]; } export class DatabaseService { private client: http.HttpRequest; private apiBase: string https://api.yourserver.com; // 你的后端API地址 constructor() { this.client http.createHttp(); } /** * 执行远程SQL查询 * param sqlTemplate SQL语句模板 * param params 参数化查询的参数数组防止SQL注入 * returns 查询结果数组 */ async executeQuery(sqlTemplate: string, params: any[] []): Promiseany[] { const url ${this.apiBase}/api/data/query; const requestData: QueryRequest { query: sqlTemplate, parameters: params }; const options: http.HttpRequestOptions { method: http.RequestMethod.POST, header: { Content-Type: application/json, // 可在此处添加认证Token如 Authorization: Bearer ${token} }, extraData: JSON.stringify(requestData), connectTimeout: 15000, // 连接超时15秒 readTimeout: 15000, // 读取超时15秒 }; try { const result await this.client.request(url, options); if (result.responseCode 200) { const responseData: QueryResponse JSON.parse(result.result as string); if (responseData.code 0) { // 假设0为业务成功码 return responseData.data; } else { throw new Error(业务错误: ${responseData.message}); } } else { throw new Error(HTTP错误: ${result.responseCode}); } } catch (err) { const error err as BusinessError; console.error(数据库查询请求失败:, error.code, error.message); throw error; // 抛出错误由调用方处理UI提示 } } /** * 销毁HTTP客户端释放资源 */ destroy() { this.client.destroy(); } }3. 在 Worker 线程中调用服务为避免耗时操作阻塞主线程数据库查询应在 Worker 中执行。// workers/DbWorker.ets import worker from kit.ArkTS; import { DatabaseService } from ../model/DatabaseService; const dbService new DatabaseService(); const workerPort worker.workerPort; // 监听主线程消息 workerPort.onmessage async function(e) { const { id, sql, params } e.data; // id用于关联请求和响应 try { const data await dbService.executeQuery(sql, params); // 查询成功将结果发回主线程 workerPort.postMessage({ id, success: true, data }); } catch (error) { // 查询失败将错误信息发回主线程 workerPort.postMessage({ id, success: false, error: (error as Error).message }); } }4. 在 UI 组件中使用在 ArkUI 组件中创建 Worker 并与之通信更新 UI。// pages/Index.ets import { worker } from kit.ArkTS; Entry Component struct Index { State queryResult: any[] []; State isLoading: boolean false; private dbWorker: worker.ThreadWorker | null null; aboutToAppear() { // 页面出现时创建Worker this.dbWorker new worker.ThreadWorker(workers/DbWorker.ets); this.dbWorker.onmessage (e) { this.isLoading false; const { id, success, data, error } e.data; if (success) { this.queryResult data; } else { // 使用promptAction.showToast提示用户 console.error(查询失败:, error); } }; } aboutToDisappear() { // 页面销毁时终止Worker if (this.dbWorker) { this.dbWorker.terminate(); } } build() { Column() { if (this.isLoading) { LoadingProgress().width(50) } List(this.queryResult) { // ...渲染列表 } Button(查询数据) .onClick(() { this.isLoading true; // 向Worker发送查询任务 this.dbWorker?.postMessage({ id: 1, sql: SELECT * FROM users LIMIT 10, params: [] }); }) } } }二、 PC端特化架构基于 Electron 的桌面数据库工具此方案适用于功能复杂的专业桌面工具利用 Electron 在鸿蒙 PC 上运行 Node.js 环境可直接使用成熟的数据库驱动。1. 架构运行链路Electron 主进程 (main.js)负责创建窗口、管理生命周期并作为 Node.js 运行时加载mysql2或pg等原生驱动。渲染进程 (Renderer)使用 React/Vue 等框架构建 UI通过 Electron 的ipcRenderer与主进程通信。预加载脚本 (preload.js)作为安全桥梁向渲染进程暴露特定的 API。2. 主进程代码 (Node.js)主进程负责建立真实的数据库连接。// main.js (Electron Main Process) const { app, BrowserWindow, ipcMain } require(electron) // 以 PostgreSQL 为例使用 pg 库 const { Client } require(pg) let mainWindow function createWindow () { mainWindow new BrowserWindow({ width: 1200, height: 800, webPreferences: { preload: path.join(__dirname, preload.js) // 预加载脚本 } }) mainWindow.loadFile(index.html) } app.whenReady().then(() { createWindow() }) // 监听来自渲染进程的数据库查询请求 ipcMain.handle(db-query, async (event, config, sql) { const client new Client({ host: config.host, port: config.port, user: config.user, password: config.password, database: config.database, }) try { await client.connect() const res await client.query(sql) return { success: true, data: res.rows } } catch (err) { console.error(err) return { success: false, error: err.message } } finally { await client.end() } })3. 预加载脚本 (安全桥梁)// preload.js const { contextBridge, ipcRenderer } require(electron) contextBridge.exposeInMainWorld(dbAPI, { query: (config, sql) ipcRenderer.invoke(db-query, config, sql) })4. 渲染进程代码 (前端)前端通过暴露的window.dbAPI调用数据库功能。// renderer.ts (在渲染进程中) async function fetchData() { const config { host: your-db-host, port: 5432, user: your-user, password: your-password, database: your-db }; const sql SELECT * FROM users LIMIT 10; const result await (window as any).dbAPI.query(config, sql); if (result.success) { console.log(查询结果:, result.data); // 更新UI } else { console.error(查询失败:, result.error); } }三、 本地数据持久化基于 RelationalStore 的缓存与状态管理当应用处于弱网或离线状态时远程 API 请求会失败。标准的做法是利用鸿蒙内置的关系型数据库RelationalStore作为本地缓存将远程拉取的数据落盘实现“离线可用”的体验。核心代码示例ArkTSimport { relationalStore } from kit.ArkData; import { common } from kit.AbilityKit; export class LocalCacheManager { private rdbStore: relationalStore.RdbStore | undefined undefined; // 1. 初始化本地数据库 async init(context: common.UIAbilityContext) { const config: relationalStore.StoreConfig { name: db_cache.db, securityLevel: relationalStore.SecurityLevel.S1 }; this.rdbStore await relationalStore.getRdbStore(context, config); // 创建本地缓存表 await this.rdbStore.executeSql( CREATE TABLE IF NOT EXISTS USER_CACHE ( ID INTEGER PRIMARY KEY AUTOINCREMENT, USER_ID INTEGER, DATA TEXT, SYNC_TIME INTEGER ) ); } // 2. 将远程拉取的数据写入本地缓存 async saveToCache(userId: number, jsonData: string) { const bucket: relationalStore.ValuesBucket { USER_ID: userId, DATA: jsonData, SYNC_TIME: Date.now() }; await this.rdbStore?.insert(USER_CACHE, bucket); } // 3. 离线状态下读取本地数据 async getFromCache(userId: number): Promisestring | null { const predicates new relationalStore.RdbPredicates(USER_CACHE); predicates.equalTo(USER_ID, userId).orderByDesc(SYNC_TIME).limitAs(1); const resultSet await this.rdbStore?.query(predicates); if (resultSet resultSet.goToNextRow()) { const data resultSet.getString(resultSet.getColumnIndex(DATA)); resultSet.close(); // ️ 关键用完必须关闭 ResultSet 防止连接池耗尽 return data; } resultSet?.close(); return null; } }四、 数据库版本升级平滑迁移与防数据丢失随着业务迭代本地缓存表或应用内置数据库的结构必然发生变化如新增字段。必须通过版本号控制机制执行增量迁移 SQL防止用户升级应用后丢失历史数据。核心代码示例ArkTSasync function upgradeDatabase(store: relationalStore.RdbStore): Promisevoid { const currentVersion store.version; // 从 v1 升级到 v2新增 TAG 字段 if (currentVersion 2) { await store.executeSql(ALTER TABLE USER_CACHE ADD COLUMN TAG TEXT DEFAULT \\); store.version 2; } // 从 v2 升级到 v3为高频查询字段添加索引 if (currentVersion 3) { await store.executeSql(CREATE INDEX IF NOT EXISTS idx_user_id ON USER_CACHE(USER_ID)); store.version 3; } }五、 跨设备一致性分布式数据同步鸿蒙的核心优势在于分布式软总线。对于多端协同的数据库管理工具可利用SyncConfig将本机的数据增量推送到用户的平板或 PC 端实现无缝接续。核心代码示例ArkTSimport { relationalStore } from kit.ArkData; async function syncDataToOtherDevices(store: relationalStore.RdbStore, targetDeviceId: string) { const syncConfig: relationalStore.SyncConfig { mode: relationalStore.SyncMode.SYNC_MODE_PUSH, // 采用推送模式 devices: [targetDeviceId] // 指定目标设备ID }; try { await store.sync(syncConfig); console.info(跨设备数据同步成功); } catch (err) { console.error(同步失败: ${(err as BusinessError).message}); } }六、 数据安全与合规加密存储与手动备份对于包含敏感信息的数据库工具除了网络传输使用 HTTPS本地落盘的数据也必须加密。同时需提供数据库备份能力以防沙箱数据意外损坏。核心代码示例ArkTSexport class SecureDbManager { // 1. 动态更改数据库加密密钥 async changeEncryptionKey(store: relationalStore.RdbStore, newKey: Uint8Array) { try { await store.changeEncryptKey(newKey); console.info(数据库加密密钥已更新); } catch (err) { console.error(更改密钥失败:, (err as BusinessError).message); } } // 2. 将数据库安全备份到应用沙箱的指定目录 async backupDatabase(store: relationalStore.RdbStore, backupPath: string) { try { await store.backup(backupPath); console.info(数据库已成功备份至: ${backupPath}); } catch (err) { console.error(数据库备份失败:, (err as BusinessError).message); } } }七、 现成商业工具Navicat Premium Lite 鸿蒙化对于希望直接使用成熟工具的用户Navicat Premium Lite已完成鸿蒙生态的初步适配是连接和管理多种数据库的便捷选择。多库支持全面兼容 MySQL、PostgreSQL、SQL Server、SQLite、MariaDB 以及国产的 OceanBase、TiDB、PolarDB 等。安全连接支持通过 SSH 隧道和 SSL/TLS 双重加密保障远程访问安全。跨端协同支持连接配置、查询脚本通过 Navicat Cloud 跨设备实时同步。开发者可直接在鸿蒙 PC 应用市场搜索下载无需自行从零构建底层驱动。线程调度 (Critical)鸿蒙规定 UI 操作必须在主线程执行。无论是通过 HTTP 请求还是本地驱动连接数据库查询均属于耗时操作必须在子线程如 Worker中完成随后通过UITaskDispatcher或状态管理切换到主线程更新 UI否则会导致应用无响应ANR。网络安全红线推荐方案采用 API 中间件模式数据库不直接暴露在公网。直连方案不推荐若必须直连远程数据库必须开启 IP 白名单仅允许 App 所在设备的 IP 访问。严禁在客户端代码中硬编码数据库用户名和密码应通过安全的配置文件或系统加密存储读取。异常与超时处理移动网络环境复杂需妥善处理网络断开、连接超时、SQL 语法错误等异常。设置合理的connectTimeout和readTimeout并通过 Toast 等方式友好地提示用户提升 App 稳定性。驱动兼容性不同数据库的 JDBC 驱动类和 URL 格式不同如 MySQL 使用com.mysql.cj.jdbc.Driver在封装底层工具类时需根据实际数据库类型动态调整。