前言
数据库存储是我们常用的存储方式之一,对大批量数据有增、删、改、查操作需求时,我们就会想到使用数据库,Flutter中提供了一个sqflite插件供我们用于大量数据执行CRUD操作。本篇我们就来一起学习sqflite的使用。
sqflite是一款轻量级的关系型数据库,类似SQLite。
在Flutter平台我们使用sqflite库来同时支持Android 和iOS。
sqflite使用
引入插件
在pubspec.yaml文件中添加path_provider插件,最新版本为1.0.0,如下:
1
2
3
4
5
|
dependencies: flutter: sdk: flutter #sqflite插件 sqflite: 1.0 . 0 |
然后命令行执行flutter packages get即可将插件下载到本地。
数据库操作方法介绍
1. 插入操作
插入数据操作有两个方法:
1
2
3
4
|
Future< int > rawInsert(String sql, [List<dynamic> arguments]); Future< int > insert(String table, Map<String, dynamic> values, {String nullColumnHack, ConflictAlgorithm conflictAlgorithm}); |
rawInsert方法第一个参数为一条插入sql语句,可以使用?作为占位符,通过第二个参数填充数据。
insert方法第一个参数为操作的表名,第二个参数map中是想要添加的字段名和对应字段值。
2. 查询操作
查询操作同样实现了两个方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
Future<List<Map<String, dynamic>>> query(String table, {bool distinct, List<String> columns, String where, List<dynamic> whereArgs, String groupBy, String having, String orderBy, int limit, int offset}); Future<List<Map<String, dynamic>>> rawQuery(String sql, [List<dynamic> arguments]); |
query方法第一个参数为操作的表名,后边的可选参数依次表示是否去重、查询字段、WHERE子句(可使用?作为占位符)、WHERE子句占位符参数值、GROUP BY子句、HAVING子句、ORDER BY子句、查询的条数、查询的偏移位等。
rawQuery方法第一个参数为一条查询sql语句,可以使用?作为占位符,通过第二个参数填充数据。
3. 修改操作
修改操作同样实现了两个方法:
1
2
3
4
5
6
|
Future< int > rawUpdate(String sql, [List<dynamic> arguments]); Future< int > update(String table, Map<String, dynamic> values, {String where, List<dynamic> whereArgs, ConflictAlgorithm conflictAlgorithm}); |
rawUpdate方法第一个参数为一条更新sql语句,可以使用?作为占位符,通过第二个参数填充数据。
update方法第一个参数为操作的表名,第二个参数为修改的字段和对应值,后边的可选参数依次表示WHERE子句(可使用?作为占位符)、WHERE子句占位符参数值、发生冲突时的操作算法(包括回滚、终止、忽略等等)。
4. 删除操作
修改操作同样实现了两个方法:
1
2
3
|
Future< int > rawDelete(String sql, [List<dynamic> arguments]); Future< int > delete(String table, {String where, List<dynamic> whereArgs}); |
rawDelete方法第一个参数为一条删除sql语句,可以使用?作为占位符,通过第二个参数填充数据。
delete方法第一个参数为操作的表名,后边的可选参数依次表示WHERE子句(可使用?作为占位符)、WHERE子句占位符参数值。
举个栗子
我们以图书管理系统来举例。
首先,我们创建一个书籍类,包括书籍ID、书名、作者、价格、出版社等信息。
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
|
final String tableBook = 'book' ; final String columnId = '_id' ; final String columnName = 'name' ; final String columnAuthor = 'author' ; final String columnPrice = 'price' ; final String columnPublishingHouse = 'publishingHouse' ; class Book { int id; String name; String author; double price; String publishingHouse; Map<String, dynamic> toMap() { var map = <String, dynamic>{ columnName: name, columnAuthor: author, columnPrice: price, columnPublishingHouse: publishingHouse }; if (id != null ) { map[columnId] = id; } return map; } Book(); Book.fromMap(Map<String, dynamic> map) { id = map[columnId]; name = map[columnName]; author = map[columnAuthor]; price = map[columnPrice]; publishingHouse = map[columnPublishingHouse]; } } |
其次,我们开始实现数据库相关操作:
1. 创建数据库文件和对应的表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
// 获取数据库文件的存储路径 var databasesPath = await getDatabasesPath(); String path = join(databasesPath, 'demo.db' ); //根据数据库文件路径和数据库版本号创建数据库表 db = await openDatabase(path, version: 1 , onCreate: (Database db, int version) async { await db.execute( '' ' CREATE TABLE $tableBook ( $columnId INTEGER PRIMARY KEY, $columnName TEXT, $columnAuthor TEXT, $columnPrice REAL, $columnPublishingHouse TEXT) '' '); }); |
2. CRUD操作实现
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
|
// 插入一条书籍数据 Future<Book> insert(Book book) async { book.id = await db.insert(tableBook, book.toMap()); return book; } // 查找所有书籍信息 Future<List<Book>> queryAll() async { List<Map> maps = await db.query(tableBook, columns: [ columnId, columnName, columnAuthor, columnPrice, columnPublishingHouse ]); if (maps == null || maps.length == 0 ) { return null ; } List<Book> books = []; for ( int i = 0 ; i < maps.length; i++) { books.add(Book.fromMap(maps[i])); } return books; } // 根据ID查找书籍信息 Future<Book> getBook( int id) async { List<Map> maps = await db.query(tableBook, columns: [ columnId, columnName, columnAuthor, columnPrice, columnPublishingHouse ], where: '$columnId = ?' , whereArgs: [id]); if (maps.length > 0 ) { return Book.fromMap(maps.first); } return null ; } // 根据ID删除书籍信息 Future< int > delete( int id) async { return await db.delete(tableBook, where: '$columnId = ?' , whereArgs: [id]); } // 更新书籍信息 Future< int > update(Book book) async { return await db.update(tableBook, book.toMap(), where: '$columnId = ?' , whereArgs: [book.id]); } |
3. 关闭数据库
数据库对象使用完之后要在适当的时候关闭掉,可在helper类中实现以下方法。
1
|
Future close() async => db.close(); |
事务
sqflite同时支持事务,通过事务可以将多条原子操作放在一起执行,保证操作要么全部执行完成,要么都不执行。
比如有两条书籍数据必须全部插入书库中才算添加成功,则使用如下方法
1
2
3
4
5
6
7
8
9
10
|
Future<bool> insertTwoBook(Book book1, Book book2) async { return await db.transaction((Transaction txn) async { book1.id = await db.insert(tableBook, book1.toMap()); book2.id = await db.insert(tableBook, book2.toMap()); print( 'book1.id = ${book1.id}, book2.id = ${book2.id}' ); return book1.id != null && book2.id != null ; }); } |
写在最后
以上介绍了sqflite中我们常用的几个操作,有了sqflite我们就可以开发更丰富的应用程序,在开发实践中大家遇到任何问题都可以给我们发消息反馈,大家一起交流探讨共同进步。针对一些用户的反馈我们将在下一篇介绍Flutter的代码调试。
好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对服务器之家的支持。
原文链接:https://juejin.im/post/5c81e48c6fb9a049b07e2534