Flutter数据库交互插件brick_supabase的使用

发布于 1周前 作者 gougou168 来自 Flutter

Flutter数据库交互插件 brick_supabase 的使用

brick_supabase 是一个用于在 Flutter 应用中与 Supabase 数据库进行交互的插件。它基于 Brick 框架,提供了便捷的模型定义和查询功能。本文将详细介绍如何使用 brick_supabase 进行数据库操作,并提供完整的示例代码。

支持的查询配置

where:

Brick 目前不支持 Supabase 的所有过滤方法。在构建 Brick 查询时,请参考以下对比表:

Brick Supabase
Compare.exact .eq
Compare.notEqual .neq
Compare.contains .like
Compare.doesNotContain .not.like
Compare.greaterThan .gt
Compare.greaterThanOrEqualTo .gte
Compare.lessThen .lt
Compare.lessThenOrEqualTo .lte
Compare.between .adj

模型定义

@SupabaseSerializable(tableName:)

指定 Supabase 表名以连接 fromupsertdelete 调用:

@SupabaseSerializable(tableName: 'users')
class User {
  final String name;

  User({required this.name});
}

@SupabaseSerializable(fieldRename:)

默认情况下,Brick 假设 Dart 字段名是 Supabase 列名的驼峰版本(例如 final String lastName => 'last_name')。可以通过设置 fieldRename 来重命名所有字段:

@SupabaseSerializable(fieldRename: FieldRename.pascal)
class User {
  final String lastName;
}

fieldRename 只是默认转换方式,可以使用 @Supabase(name:) 对单个字段进行覆盖。

@SupabaseSerializable(defaultToNull:)

upsert 操作期间转发到 Supabase 的 defaultToNull

@SupabaseSerializable(ignoreDuplicates:)

upsert 操作期间转发到 Supabase 的 ignoreDuplicates

@SupabaseSerializable(onConflict:)

upsert 操作期间转发到 Supabase 的 onConflict

字段注解

@Supabase(unique:)

连接 Supabase 的主键或任何其他索引到应用程序代码,这对 upsertdelete 操作非常有用:

@Supabase(unique: true, name: 'uuid')
final String supabaseUuid;

@Supabase(enumAsString:)

如果 API 返回的是字符串而不是整数,则可以使用此注解:

enum Hat { baseball, bowler, birthday }

@Supabase(enumAsString: true)
final List<Hat> hats;

@Supabase(name:)

重命名 Supabase 键名:

@Supabase(name: "full_name")
final String lastName;

@Supabase(foreignKey:)

当字段类型扩展模型类型时,Supabase 列应为外键:

class User extends OfflineFirstWithSupabaseModel {
  @Supabase(foreignKey: 'address_id')
  final Address address;
}

class Address extends OfflineFirstWithSupabaseModel {
  final String id;
}

@Supabase(ignoreFrom:)@Supabase(ignoreTo:)

当为 true 时,字段将被忽略,不会参与序列化或反序列化。

测试

Mocking a Supabase Instance

在测试组中快速创建一个方便的模拟服务器:

import 'package:brick_supabase/testing.dart';
import 'package:test/test.dart';

void main() {
  final mock = SupabaseMockServer(modelDictionary: supabaseModelDictionary);

  group('MyClass', () {
    setUp(mock.setUp);
    tearDown(mock.tearDown);

    test('#myMethod', () async {
      final req = SupabaseRequest<MyModel>();
      final resp = SupabaseResponse([
        await mock.serialize(MyModel(name: 'Demo 1', id: '1')),
        await mock.serialize(MyModel(name: 'Demo 2', id: '2')),
      ]);
      mock.handle({req: resp});
      final provider = SupabaseProvider(mock.client, modelDictionary: supabaseModelDictionary);
      final retrieved = await provider.get<MyModel>();
      expect(retrieved, hasLength(2));
    });
  });
}

示例代码

以下是一个完整的示例代码,展示了如何使用 brick_supabase 进行基本的 CRUD 操作:

import 'package:brick_core/core.dart';
import 'package:brick_supabase/brick_supabase.dart';
import 'package:supabase/supabase.dart';

/// 生成的适配器类
class UserAdapter extends SupabaseAdapter<User> {
  @override
  Future<User> fromSupabase(data, {required provider, repository}) async {
    return User(
      name: data['name'],
    );
  }

  @override
  Future<Map<String, dynamic>> toSupabase(instance, {required provider, repository}) async {
    return {
      'name': instance.name,
    };
  }

  @override
  final defaultToNull = false;
  @override
  final fieldsToSupabaseColumns = {'name': RuntimeSupabaseColumnDefinition(columnName: 'name')};
  @override
  final ignoreDuplicates = false;
  @override
  final onConflict = null;
  @override
  final tableName = 'users';
  @override
  final uniqueFields = {};
}

/// 生成的字典
final dictionary = SupabaseModelDictionary({
  User: UserAdapter(),
});

/// 定义模型
class User extends SupabaseModel {
  final String name;

  User({required this.name});
}

/// 定义仓库
class MyRepository extends SingleProviderRepository<SupabaseModel> {
  MyRepository(String apiUrl, String supabaseAnonKey)
      : super(
          SupabaseProvider(
            SupabaseClient(apiUrl, supabaseAnonKey),
            modelDictionary: dictionary,
          ),
        );
}

void main() async {
  final repository = MyRepository('http://localhost:8080', 'YOUR_API_KEY_HERE');

  // 获取用户列表
  final users = await repository.get<User>();
  print(users);

  // 创建新用户
  final newUser = User(name: 'John Doe');
  await repository.upsert(newUser);

  // 更新用户信息
  final updatedUser = User(name: 'Jane Doe');
  await repository.upsert(updatedUser);

  // 删除用户
  await repository.delete<User>(id: 'user_id');
}

以上代码展示了如何定义模型、适配器、字典以及如何使用仓库进行数据操作。希望这些内容能帮助你更好地理解和使用 brick_supabase 插件。


更多关于Flutter数据库交互插件brick_supabase的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter数据库交互插件brick_supabase的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何使用Flutter数据库交互插件brick_supabase的示例代码案例。这个插件允许你轻松地在Flutter应用中使用Supabase作为后端数据库。

首先,你需要确保已经在你的pubspec.yaml文件中添加了brick_supabase依赖:

dependencies:
  flutter:
    sdk: flutter
  brick_supabase: ^最新版本号 # 请替换为实际的最新版本号

然后运行flutter pub get来安装依赖。

接下来,你需要设置Supabase的客户端。这通常包括你的Supabase URL和匿名密钥。你可以在Supabase的仪表板上找到这些信息。

以下是一个完整的示例,展示如何使用brick_supabase插件进行基本的数据库操作,如插入、查询和更新数据:

import 'package:flutter/material.dart';
import 'package:brick_supabase/brick_supabase.dart';

void main() {
  // 配置Supabase客户端
  final supabaseClient = SupabaseClient(
    supabaseUrl: 'https://你的项目名.supabase.co', // 替换为你的Supabase URL
    supabaseAnonKey: '你的匿名密钥', // 替换为你的Supabase匿名密钥
  );

  runApp(MyApp(supabaseClient: supabaseClient));
}

class MyApp extends StatelessWidget {
  final SupabaseClient supabaseClient;

  MyApp({required this.supabaseClient});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Supabase Flutter Demo'),
        ),
        body: Center(
          child: SupabaseDemo(supabaseClient: supabaseClient),
        ),
      ),
    );
  }
}

class SupabaseDemo extends StatefulWidget {
  final SupabaseClient supabaseClient;

  SupabaseDemo({required this.supabaseClient});

  @override
  _SupabaseDemoState createState() => _SupabaseDemoState();
}

class _SupabaseDemoState extends State<SupabaseDemo> {
  late String resultText = '';

  @override
  void initState() {
    super.initState();
    _insertData();
    _fetchData();
    // _updateData(); // 你可以取消注释来测试更新数据
    // _deleteData(); // 你可以取消注释来测试删除数据
  }

  Future<void> _insertData() async {
    try {
      final response = await widget.supabaseClient.from('your_table_name').insert({
        'name': 'John Doe',
        'email': 'john.doe@example.com',
      });
      print('Insert Response: ${response.data}');
    } catch (e) {
      print('Error inserting data: $e');
    }
  }

  Future<void> _fetchData() async {
    try {
      final response = await widget.supabaseClient.from('your_table_name').select();
      final data = response.data!;
      if (data.isNotEmpty) {
        setState(() {
          resultText = data.first['name']!; // 显示第一个条目的名字
        });
      } else {
        setState(() {
          resultText = 'No data found';
        });
      }
    } catch (e) {
      print('Error fetching data: $e');
    }
  }

  // 示例更新函数(你可以根据需要修改)
  Future<void> _updateData() async {
    try {
      final response = await widget.supabaseClient.from('your_table_name')
          .update({'email': 'john.newemail@example.com'})
          .eq({'id': '需要更新的记录的ID'}); // 替换为实际的ID
      print('Update Response: ${response.data}');
    } catch (e) {
      print('Error updating data: $e');
    }
  }

  // 示例删除函数(你可以根据需要修改)
  Future<void> _deleteData() async {
    try {
      final response = await widget.supabaseClient.from('your_table_name')
          .delete()
          .eq({'id': '需要删除的记录的ID'}); // 替换为实际的ID
      print('Delete Response: ${response.data}');
    } catch (e) {
      print('Error deleting data: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        Text('Result: $resultText'),
        ElevatedButton(
          onPressed: () async {
            setState(() {
              resultText = 'Refreshing...';
            });
            await _fetchData();
          },
          child: Text('Refresh Data'),
        ),
      ],
    );
  }
}

在这个示例中,我们创建了一个Flutter应用,该应用使用brick_supabase插件与Supabase数据库进行交互。我们演示了如何插入、查询数据,并提供了更新和删除数据的示例函数(这些函数在initState中被注释掉了,但你可以根据需要取消注释以测试它们)。

请注意,你需要将your_table_name替换为你实际的Supabase表名,并根据需要调整其他字段和值。此外,更新和删除操作需要指定要更新或删除的记录的ID,你需要根据实际情况进行替换。

回到顶部