Flutter系列之Dart数据库编程

释放双眼,带上耳机,听听看~!

现如今数据库的发展很快,犹如百花齐放
关系型数据库、NoSQL、图数据库、嵌入式数据库……层出不穷
虽然各自应用的场景不同
但无论如何,关系型数据库使用面最广,NoSQL人气最高

Dart SDK中并没有原生的数据库驱动
但是无论是PostgreSQL还是SQLite还是MongoDB,都能找到对于的包
看了一下Pub和Github
不得不说,对数据库支持最好还是PostgreSQL和MongoDB

接下来的几篇帖子会对常用数据库作简单演示
这里说一下MySQL

MySQL应用广泛,资料也很全
MySQL驱动做得比较好的应该是sqljocky
但是Pub中READMI.md的一句话着实让人、、、汗颜
It isn’t finished, but should work for most normal use.
好吧!只能说,正式应用需谨慎

注:
sqljocky只能运行在虚拟机中
不能在浏览器端运行

pubspec.yaml


1
2
3
4
1name: Note19
2dependencies:
3  sqljocky: "^0.14.1"
4

一般情况下我们并不会在程序中创建数据库
因为大多时候虚拟主机提供的都是固定的数据库
用户并没有创建的权限

另外,删除和新建数据库、表
可以用Drop、Create if not exists命令
如果要查询数据库或表是否存在,可以通过以下sql语句


1
2
3
4
5
6
1//查询数据库TempDB是否存在
2select count(*) from information_schema.tables where table_schema='tempdb';
3
4//查询数据库TempDB中是否存在Users表
5select count(*) from information_schema.tables where table_schema='tempdb' and table_name='users';
6

Flutter系列之Dart数据库编程

main.dart


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
1import 'package:sqljocky/sqljocky.dart';
2import 'package:sqljocky/utils.dart';
3
4main() async {
5  /**
6   * 连接服务器,host默认'localhost',port默认3306
7   * 密码为空时,不设置password,数据库名称db可以省略
8   * 如果权限足够,连接服务器可以新建数据库
9   */
10  print("Opening connection");
11  var pool = new ConnectionPool(host: 'localhost', port:3306, user:'root');
12  await pool.query('drop database if exists TempDB');
13  await pool.query('create database TempDB');
14
15  /**
16   * 新建连接的时候,之前的连接资源并不会自动释放
17   * 需要调用closeConnectionsWhenNotInUse
18   * 或closeConnectionsNow
19   * 如果程序运行结束的时候,进程并没有退出
20   * 说明资源未及时释放
21   */
22  pool.closeConnectionsNow();
23
24  /**
25   * 新连接刚建的数据库
26   * 赋值给之前的pool变量
27   */
28  pool = new ConnectionPool(
29    host: 'localhost', port: 3306, user: 'root', db: 'TempDB');
30
31  /**
32   * 除了ConnectionPool.query
33   * 在'package:sqljocky/utils.dart'中
34   * utils提供了两个实用的类用来删除表和执行多条sql语句
35   */
36  print("Drop tables");
37  await new TableDropper(pool, ['users']).dropTables();
38
39  /**
40   * 也许是出于安全考虑,为了预防SQL攻击
41   * sqljocky并不支持单个字符串执行多条分号分隔的sql语句
42   * 如:"'insert into ...; insert into ..."
43   * 有可能你习惯拼接sql语句,但是
44   * 程序员不应该执行“删除地球”这样的SQL语句
45   * 而是写“删除一个行星”,然后将“地球”当作参数传入
46   * 也就是预处理
47   * 下面的代码仅仅是演示QueryRunner(ConnectionPool, List)的用法
48   * 适用于初始化数据库
49   */
50  print("Create tables");
51  await new QueryRunner(pool, [
52    'CREATE TABLE users ('
53        'name varchar(100) NOT NULL,'
54        'email varchar(100) NOT NULL)',
55    'INSERT INTO users(name, email) VALUES ("Wang","wang@qq.com")',
56    'INSERT INTO users(name, email) VALUES ("Li","li@163.com")'
57  ]).executeQueries();
58
59  /**
60   * 预处理
61   * 如果仅执行一次sql语句,可使用prepareExecute(sql, list)
62   * 如果需要执行多次sql语句,可使用executeMulti函数
63   * 再通过executeMulti(List<List>)传入参数
64   * 如果sql语句有返回值,可遍历Future<List<Results>>
65   */
66  print('Prepare insert multiLine sql');
67  var preSql = await pool.prepare(
68      "insert into users(name, email) values(?, ?)");
69  await preSql.executeMulti([
70    ['Chen', 'chen@sina.com'],
71    ['Yu', 'yu@gmail.com']
72  ]);
73
74  /**
75   * ConnectionPool也提供了执行sql语句的函数
76   * 如果sql语句有返回值,可遍历Future<Results>
77   */
78  print('Select users');
79  var results = await pool.query('select * from users');
80  results.forEach((row) {
81    print('Name: ${row[0]}, email: ${row[1]}');
82  });
83
84  /**
85   * 事务处理
86   * 下面的代码综合了事务处理和预处理
87   * 代码风格上,并没有用之前的await关键字
88   * 而是在then中注册回调函数,浓浓的Dart味道
89   * 这样省了不少临时变量的声明过程
90   *
91   * 需要说明的是
92   * sqljocky中不能通过query('start transaction')开启事务
93   * 同时,事务处理会保持连接,直到调用commit或者rollback
94   * 在提交或回滚事务的之后,不能再查询数据,否则会抛出错误
95   *
96   * commit和rollback并不会直接释放资源
97   * 需要在then函数中注册回调函数,调用close函数
98   * 否则,会进入阻塞状态
99   */
100  print('Transaction start');
101  pool.startTransaction().then((Transaction trans) {
102    trans.prepareExecute(
103        'update users set email=? where name=?',
104        ['yu@sohu.com', 'Yu']).then((_) {
105      trans.commit().then((_) {
106        print("Transaction end");
107        pool.closeConnectionsNow();
108      });
109    });
110  });
111
112  /**
113   * 释放资源
114   * 由于在上面事务处理的代码中,commit已经释放了资源
115   * 因此本句代码可以省略
116   */
117  pool.closeConnectionsWhenNotInUse();
118}
119

运行结果:
Flutter系列之Dart数据库编程
Flutter系列之Dart数据库编程

本文图片资料来源出自“Dart语言中文社区”,允许转载,转载时请务必以超链接形式标明文章原始出处  

给TA打赏
共{{data.count}}人
人已打赏
安全技术

C++ explicit关键字

2022-1-11 12:36:11

安全资讯

苹果寻求富士康帮助 加速扩张中国、印尼业务

2016-12-27 7:08:20

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索