Flutter for OpenHarmony:postgres 直连 PostgreSQL 数据库,实现 Dart 原生的高效读写(数据库驱动) 深度解析与鸿蒙适配指南

Flutter for OpenHarmony:postgres 直连 PostgreSQL 数据库,实现 Dart 原生的高效读写(数据库驱动) 深度解析与鸿蒙适配指南

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net

请添加图片描述

前言

虽然移动应用大多使用本地数据库(如 SQLite),但在某些特定场景,比如内部企业应用、数据看板,或者 Serverless 架构中,客户端直接连接远程数据库进行即时查询是非常便捷的。

postgres 是一个纯 Dart 实现的 PostgreSQL 驱动,拥有完整的协议支持,不需要任何原生库绑定(JNI/FFI)。这意味着它不仅能在服务器端(Dart VM)运行完美,同样也能在 Flutter 移动端及 Web 端流畅运行,当然也包括 OpenHarmony。

一、核心特性

  • 纯 Dart 实现:零原生依赖,全平台通用。
  • SSL/TLS 安全连接:保障数据传输安全。
  • 流式查询:支持大结果集的流式读取,避免 OOM。
  • 连接池:内置连接池管理,适应高并发场景。

通过 TCP/SSL 连接

PostgreSQL 协议交互

执行 SQL 语句

底层查询

原始结果集

映射后的 Dart 对象

OpenHarmony 应用

远程数据库服务器

内置连接池

数据库实例

Flutter 组件渲染

二、集成与配置

2.1 添加依赖

dependencies:postgres: ^3.5.9 

2.2 连接配置 (SSLMode)

在公网环境连接数据库,强烈建议开启 SSL。

import'package:postgres/postgres.dart';final endpoint =Endpoint( host:'db.example.com', port:5432, database:'my_db', username:'user', password:'password',);final connection =awaitConnection.open( endpoint, settings:ConnectionSettings( sslMode:SslMode.require,// 强制 SSL),);
在这里插入图片描述

三、核心操作与示例

3.1 示例一:执行简单查询

查询用户列表并将结果映射为 Dart 对象。

Future<void>queryUsers()async{// 假设已有 connectionfinal result =await connection.execute('SELECT id, name FROM users WHERE active = @active', parameters:{'active':true},);for(final row in result){print('User: ${row[0]} - ${row[1]}');}}
在这里插入图片描述

3.2 示例二:事务处理

转账操作必须在事务中完成。

Future<void>transferMoney(int fromId, int toId, double amount)async{await connection.runTx((session)async{// 1. 扣款await session.execute('UPDATE accounts SET balance = balance - @amount WHERE id = @from', parameters:{'amount': amount,'from': fromId},);// 2. 加款await session.execute('UPDATE accounts SET balance = balance + @amount WHERE id = @to', parameters:{'amount': amount,'to': toId},);// 如果抛异常,自动回滚});}
在这里插入图片描述

3.3 示例三:监听数据库通知 (LISTEN/NOTIFY)

PostgreSQL 有个超酷的功能:发布订阅。App 可以实时收到数据库变更通知。

Future<void>listenChanges()async{// 建立专用连接用于监听final conn =awaitConnection.open(endpoint);// 订阅频道 'user_updates'await conn.execute("LISTEN user_updates");// 监听通知流 conn.channels['user_updates']?.listen((payload){print('收到数据库通知: $payload');// 刷新 UI});}
在这里插入图片描述

四、OpenHarmony 平台适配

4.1 网络权限

连接远程数据库必须声明网络权限。

"requestPermissions":[{"name":"ohos.permission.INTERNET"}]

4.2 安全与证书

如果在内网且自签名证书,需要在连接时添加受信任的根证书。postgres 库允许通过 SecurityContext 自定义证书验证逻辑。

五、完整实战示例:实时数据看板

本示例将连接一个远程 PostgreSQL 数据库,并展示实时更新的销售数据。每当有新订单插入时(通过 LISTEN/NOTIFY),看板自动刷新。

5.1 示例代码

import'dart:async';import'package:flutter/material.dart';import'package:postgres/postgres.dart';voidmain(){runApp(constMaterialApp(home:DashboardPage()));}classDashboardPageextendsStatefulWidget{constDashboardPage({super.key});@overrideState<DashboardPage>createState()=>_DashboardPageState();}class _DashboardPageState extendsState<DashboardPage>{Connection? _conn;List<Map<String,dynamic>> _salesData =[]; bool _connecting =true;String _error ='';@overridevoidinitState(){super.initState();_connectDB();}Future<void>_connectDB()async{try{// ⚠️ 真实项目中不要硬编码密码!应通过安全方式获取final endpoint =Endpoint( host:'192.168.1.100',// 替换为你的服务器 IP port:5432, database:'sales_db', username:'flutter_app', password:'secure_password',); _conn =awaitConnection.open(endpoint, settings:ConnectionSettings(sslMode:SslMode.disable));// 订阅实时更新await _conn!.execute("LISTEN new_sale"); _conn!.channels['new_sale']?.listen((_)=>_refreshData());await_refreshData();// 初始加载setState((){ _connecting =false; _error ='';});}catch(e){setState((){ _connecting =false; _error ='连接失败: $e';});}}Future<void>_refreshData()async{if(_conn ==null)return;try{final result =await _conn!.execute('SELECT product, amount, created_at FROM sales ORDER BY created_at DESC LIMIT 20');final data = result.map((row)=>{'product': row[0]asString,'amount': row[1]as double,'time': row[2]asDateTime,}).toList();if(mounted){setState(()=> _salesData = data);}}catch(e){print('查询失败: $e');}}@overridevoiddispose(){ _conn?.close();super.dispose();}@overrideWidgetbuild(BuildContext context){returnScaffold( appBar:AppBar(title:constText('实时销售看板')), body: _connecting ?constCenter(child:CircularProgressIndicator()): _error.isNotEmpty ?Center(child:Text(_error, style:constTextStyle(color:Colors.red))):RefreshIndicator( onRefresh: _refreshData, child:ListView.builder( itemCount: _salesData.length, itemBuilder:(context, index){final item = _salesData[index];returnListTile( leading:constIcon(Icons.shopping_cart), title:Text(item['product']), subtitle:Text(item['time'].toString().substring(11,19)), trailing:Text('¥${item['amount']}', style:constTextStyle(fontWeight:FontWeight.bold, fontSize:16, color:Colors.green),),);},),), floatingActionButton:FloatingActionButton( tooltip:'模拟下单', child:constIcon(Icons.add), onPressed:(){// 仅用于演示:客户端插入一条数据触发通知 _conn?.execute("INSERT INTO sales (product, amount) VALUES ('OpenHarmony Device', 999.0); NOTIFY new_sale;");},),);}}
在这里插入图片描述

六、总结

在 OpenHarmony 上通过 postgres 库直连数据库,为开发者提供了极大的灵活性,尤其适合快速原型开发、内部工具以及实时性要求极高的场景。

最佳实践

  1. 安全性:不要把生产环境数据库端口直接暴露在公网,建议配合 VPN 或 SSH 隧道使用,或者至少限制 IP 白名单。
  2. 连接池:虽然库内置了连接池,但移动端资源有限,应谨慎开启过多连接。通常一个长连接用于监听,短连接按需使用。
  3. 架构设计:对于大型 C 端应用,仍建议通过 HTTP API 访问数据,直连仅限特定后端或管理端场景。

Read more

【Java 开发日记】阻塞队列有哪些?拒绝策略有哪些?

【Java 开发日记】阻塞队列有哪些?拒绝策略有哪些?

目录 阻塞队列有哪些? 拒绝策略有哪些? 面试回答 阻塞队列有哪些? 在Java的java.util.concurrent包里面,阻塞队列的实现挺多的,我们可以根据它的功能和结构来记,主要分这么几类: 1. 按容量划分: * 有界队列: 就是队列有固定的容量。 * ArrayBlockingQueue: 最经典的一个,底层是数组,创建时必须指定大小。它的生产和消费用同一把锁,性能相对稳定。 * LinkedBlockingQueue: 底层是链表,它既可以是有界的(构造时指定容量),也可以默认是无界的(默认是Integer.MAX_VALUE,几乎相当于无界)。它的生产和消费用了两把锁,在高并发场景下吞吐量通常比ArrayBlockingQueue更高。 * 无界队列: 理论上是无限的,只要内存够就能一直放。 * PriorityBlockingQueue: 一个支持优先级排序的无界队列。元素必须实现Comparable接口,或者构造时传入Comparator。它出队的顺序是按优先级来的,不是先进先出 * DelayQueue: 一个很特殊的队

By Ne0inhk
Java 大视界 -- Java 大数据机器学习模型在金融产品创新与客户需求匹配中的实战应用(417)

Java 大视界 -- Java 大数据机器学习模型在金融产品创新与客户需求匹配中的实战应用(417)

Java 大视界 -- Java 大数据机器学习模型在金融产品创新与客户需求匹配中的实战应用(417) * 引言:从 3.8% 到 22.5% 的转化率跃升 —— 传统银行的破局之路 * 正文: * 一、传统金融产品模式的 4 大核心痛点(某城商行实战调研) * 二、金融级机器学习架构设计(5 层闭环,满足监管与性能要求) * 架构设计的 3 个金融级原则(区别于互联网场景) * 三、核心模块详解(附完整可运行代码与避坑指南) * 3.1 模块 1:客户画像模型(KMeans + 随机森林,输出 360° 标签) * 3.1.1 画像模型设计(双阶段标签体系) * 3.1.

By Ne0inhk
Java 中间件:RocketMQ 顺序消息(全局/分区顺序)

Java 中间件:RocketMQ 顺序消息(全局/分区顺序)

👋 大家好,欢迎来到我的技术博客! 📚 在这里,我会分享学习笔记、实战经验与技术思考,力求用简单的方式讲清楚复杂的问题。 🎯 本文将围绕Java中间件这个话题展开,希望能为你带来一些启发或实用的参考。 🌱 无论你是刚入门的新手,还是正在进阶的开发者,希望你都能有所收获! 文章目录 * Java 中间件:RocketMQ 顺序消息(全局 / 分区顺序) * 什么是顺序消息? * RocketMQ 顺序消息的工作原理 * 全局顺序 vs 分区顺序 * RocketMQ 顺序消息的核心机制 * 全局顺序消息的实现 * 全局顺序的配置要求 * Java 代码示例:全局顺序消息 * 全局顺序的局限性 * 分区顺序消息的实现 * 分区顺序的设计思路 * Java 代码示例:分区顺序消息 * 分区顺序的关键要点 * 顺序消息的消费机制详解 * ConsumeOrderlyStatus 枚举 * 消费失败的处理机制 * 并发消费 vs 顺序消费

By Ne0inhk
Java 常见Exception全面解析:出现场景、错误排查与代码修正实战

Java 常见Exception全面解析:出现场景、错误排查与代码修正实战

文章目录 * 课程导言 * 适用对象 * 学习目标 * 课程安排 * 教学方式 * 第一部分:Java异常体系回顾(约10分钟) * 1.1 异常是什么? * 1.2 Java异常体系结构 * 1.3 异常信息解读 * 第二课时(上):运行时异常深度剖析(约30分钟) * 2.1 NullPointerException(空指针异常) * 现象描述 * 出现场景 * 堆栈分析示例 * 排查方法流程图 * 代码修正与预防 * 2.2 ArrayIndexOutOfBoundsException(数组下标越界异常) * 现象描述 * 出现场景 * 堆栈分析示例 * 排查方法 * 代码修正与预防 * 2.3 ClassCastException(类型转换异常) * 现象描述 * 出现场景 * 堆栈分析示例 * 排查方法 * 代码修正与预防 * 2.

By Ne0inhk