Flutter对象关系映射插件needle_orm的使用

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

Flutter对象关系映射插件needle_orm的使用

支持的数据库

  • ✅ PostgreSQL
  • ✅ MariaDB(事务功能尚不可用)

支持的注解

其他一些有用的注解,类似于 Ebean ORM for Java/Kotlin:

定义模型

[@Entity](/user/Entity)()
abstract class _BaseModel {
  [@ID](/user/ID)()
  int? _id; // 主键

  [@Version](/user/Version)()
  int? _version; // 版本号

  [@SoftDelete](/user/SoftDelete)()
  bool? _deleted; // 软删除标志

  [@WhenCreated](/user/WhenCreated)()
  DateTime? _createdAt; // 创建时间

  [@WhenModified](/user/WhenModified)()
  DateTime? _updatedAt; // 更新时间

  [@WhoCreated](/user/WhoCreated)()
  String? _createdBy; // 创建者登录名

  [@WhoModified](/user/WhoModified)()
  String? _lastUpdatedBy; // 最后更新者登录名

  [@Column](/user/Column)()
  String? _remark; // 备注

  _BaseModel();
}

[@Table](/user/Table)(name: 'tbl_user')
[@Entity](/user/Entity)()
class _User extends _BaseModel {
  [@Column](/user/Column)()
  String? _name; // 用户名

  [@Column](/user/Column)()
  String? _loginName; // 登录名

  [@Column](/user/Column)()
  String? _address; // 地址

  [@Column](/user/Column)()
  int? _age; // 年龄

  [@OneToMany](/user/OneToMany)(mappedBy: "_author")
  List<_Book>? books; // 用户拥有的书籍

  _User();
}

[@Table](/user/Table)()
[@Entity](/user/Entity)()
class _Book extends _BaseModel {
  [@Column](/user/Column)()
  String? _title; // 书名

  [@Column](/user/Column)()
  double? _price; // 价格

  [@ManyToOne](/user/ManyToOne)()
  _User? _author; // 作者

  [@Lob](/user/Lob)()
  List<int>? _image; // 图片 (BLOB)

  [@Lob](/user/Lob)()
  String? _content; // 内容 (CLOB)

  _Book();
}

增强业务逻辑

extension Biz_User on User {
  bool isAdmin() {
    return name!.startsWith('admin');
  }

  void beforeInsert() {
    _version = 1;
    _deleted = false;
    print('before insert user ....');
  }

  void afterInsert() {
    print('after insert user ....');
  }
}

使用示例

Future<Database> initPostgreSQL() async {
  return PostgreSqlPoolDatabase(PgPool(
    PgEndpoint(
      host: 'localhost',
      port: 5432,
      database: 'appdb',
      username: 'postgres',
      password: 'postgres',
    ),
    settings: PgPoolSettings()
      ..maxConnectionAge = Duration(hours: 1)
      ..concurrency = 5,
  ));
}

void main() async {
  Database.register("dbPostgres", await initPostgreSQL());

  // 创建或更新用户
  {
    var user = User();
    user
      ..name = 'administrator'
      ..address = 'abc'
      ..age = 23
      ..save(); // 或者 insert()

    print('user saved, id= ${user.id}');

    user
      ..name = 'another name'
      ..save(); // 或者 update()

    // 调用业务方法
    print('is admin? ${user.isAdmin()}');

    // 转换为Map,也可以用于生成JSON
    var valueMap = user.toMap();
    // 或者只输出某些字段
    valueMap = user.toMap(fields:'id,name');

    // 从Map加载数据
    user.loadMap({"name": 'admin123', "xxxx": 'xxxx'});

    var book = Book();
    book
      ..author = user
      ..title = 'Dart'
      ..price = 14.99
      ..insert();

    // toMap支持嵌套字段:'author(id,name)'
    valueMap = book.toMap(fields:'id,title,price,author(id,name)');
  }

  // 类型查询
  {
    Book.query()
      ..title.startsWith('dart')
      ..price.between(10.0, 20.0)
      ..author.apply((author) {
        author
          ..age.ge(18)
          ..address.startsWith('China Shanghai');
      })
      ..orders = [Book.query().price.desc()]
      ..offset = 10
      ..maxRows = 20  // limit
      ..findList();
  }

  // 软删除
  {
    var q = Book.query()
      ..price.between(18, 19)
      ..title.endsWith('test');
    var total = await q.count();  // 不包括已删除记录
    var totalWithDeleted = await q.count(includeSoftDeleted: true);
    print('found books , total: $total, totalWithDeleted: $totalWithDeleted');

    int deletedCount = await q.delete();
    print('soft deleted books: $deletedCount');

    total = await q.count();
    totalWithDeleted = await q.count(includeSoftDeleted: true);
    print('found books after soft delete , total: $total, totalWithDeleted: $totalWithDeleted');
  }

  // 永久删除
  {
    var q = Book.query()
    ..price.between(100, 1000);
    var total = await q.count();

    print('found expensive books, total count: $total');

    int deletedCount = await q.deletePermanent();
    print('permanent deleted books : $deletedCount');
  }

  // 批量插入
  {
    var n = 10;
    var users = <User>[];
    for (int i = 0; i < n; i++) {
      var user = User()
        ..name = 'name_$i'
        ..address = 'China Shanghai street_$i'
        ..age = (n * 0.1).toInt();
      users.add(user);
    }
    print('users created');
    await User.query().insertBatch(users, batchSize: 5);
    print('users saved');
    var idList = users.map((e) => e.id).toList();
    print('ids: $idList');
  }

  // 在同一查询中的模型缓存
  {
    var user = User()..name = 'cach_name';
    await user.save();

    var book1 = Book()
      ..author = user
      ..title = 'book title1';
    var book2 = Book()
      ..author = user
      ..title = 'book title2';
    await book1.save();
    await book2.save();

    var q = Book.query()..id.IN([book1.id!, book2.id!]);
    var books = await q.findList();
    // books[0].author 应该与 books[1].author 相同
    print('used cache? ${books[0].author == books[1].author}');
  }

  // 事务:仅在PostgreSQL上工作,在MariaDB上仍存在问题
  {
    var q = User.query();
    print('count before insert : ${await q.count()}');
    var db2 = await initPostgreSQL();
    await db2.transaction((db) async {
      var n = 50;
      for (int i = 1; i < n; i++) {
        var user = User()
          ..name = 'tx_name_$i'
          ..address = 'China Shanghai street_$i ' * i
          ..age = n;
        await user.save(db: db); // 第10次循环时因为地址太长而抛出回滚异常
        print('\t used saved with id: ${user.id}');
      }
    });

    // 因为回滚异常,下一行永远不会执行。
    // print('count after insert : ${await q.count()}');
  }
}

更多关于Flutter对象关系映射插件needle_orm的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter对象关系映射插件needle_orm的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter项目中使用needle_orm对象关系映射插件的代码案例。needle_orm是一个用于Flutter的ORM库,它简化了SQLite数据库的操作。以下是一个简单的示例,展示如何定义模型、创建数据库、插入数据以及查询数据。

1. 添加依赖

首先,在你的pubspec.yaml文件中添加needle_orm的依赖:

dependencies:
  flutter:
    sdk: flutter
  needle_orm: ^最新版本号

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

2. 定义模型

接下来,定义一个模型类。模型类需要继承自BaseModel并指定表名。此外,还需要使用@Column注解来标记字段。

import 'package:needle_orm/needle_orm.dart';

@Table(name: 'users')
class User extends BaseModel {
  @Column(name: 'name', type: ColumnType.text, notNull: true)
  String name;

  @Column(name: 'age', type: ColumnType.integer, notNull: true)
  int age;

  // 默认构造函数
  User({required this.name, required this.age});

  // 从数据库构造
  User.fromMap(Map<String, dynamic> map) {
    name = map['name'];
    age = map['age'];
  }

  // 转换为Map,用于数据库操作
  Map<String, dynamic> toMap() {
    return {'name': name, 'age': age};
  }
}

3. 初始化数据库

在你的应用中初始化数据库并创建表。

import 'package:flutter/material.dart';
import 'package:needle_orm/needle_orm.dart';
import 'user_model.dart'; // 假设你的User类在这个文件中

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Needle ORM Example'),
        ),
        body: DatabaseDemo(),
      ),
    );
  }
}

class DatabaseDemo extends StatefulWidget {
  @override
  _DatabaseDemoState createState() => _DatabaseDemoState();
}

class _DatabaseDemoState extends State<DatabaseDemo> {
  late DatabaseManager dbManager;

  @override
  void initState() {
    super.initState();
    initDatabase();
  }

  Future<void> initDatabase() async {
    dbManager = await DatabaseManager.getInstance(
      databasesPath: 'example.db', // 数据库文件路径
      models: [User], // 注册模型
    );

    // 创建表
    await dbManager.createAllTables();
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: ElevatedButton(
        onPressed: () async {
          await insertAndQueryData();
        },
        child: Text('Insert and Query Data'),
      ),
    );
  }

  Future<void> insertAndQueryData() async {
    // 插入数据
    User user = User(name: 'Alice', age: 30);
    await dbManager.insert(user);

    // 查询数据
    List<User> users = await dbManager.queryAll<User>();
    print('Queried Users: ${users.map((u) => u.toMap()).toList()}');
  }
}

4. 运行应用

运行你的Flutter应用,点击按钮后,应该会看到控制台输出插入并查询到的用户数据。

注意事项

  • 确保你已经正确配置了Android和iOS的权限,以便应用可以访问数据库。
  • needle_orm的具体API可能会随着版本的更新而变化,请参考官方文档获取最新信息。

这个示例展示了如何使用needle_orm进行基本的数据库操作。根据你的需求,你可以进一步扩展这个示例,例如添加更多字段、实现复杂的查询、处理数据更新和删除等。

回到顶部