floor 0.1.0
floor: ^0.1.0 copied to clipboard
A supportive SQLite abstraction for your Flutter applications. This library is the runtime dependency.
Floor #
A supportive SQLite abstraction for your Flutter applications.
The Floor library provides a lightweight SQLite abstraction with automatic mapping between in-memory objects and database rows while still offering full control of the database with the use of SQL.
It's important to note that this library is not a full featured ORM like Hibernate and will never be. Thus not supporting automatic relationship mapping is intentional.
This package is still in an early phase and the API will likely change.
Table of contents #
- How to use this library
- Querying
- Persisting Data Changes
- Transactions
- Entities
- Foreign Keys
- Examples
- Naming
- Bugs and Feedback
- License
How to use this library #
-
Add the runtime dependency
flooras well as the generatorfloor_generatorto yourpubspec.yaml. The third dependency isbuild_runnerwhich has to be included as a dev dependency just like the generator.-
floorholds all the code you are going to use in your application. -
floor_generatorincludes the code for generating the database classes. -
build_runnerenables a concrete way of generating source code files.
dependencies: flutter: sdk: flutter floor: git: url: https://github.com/vitusortner/floor.git path: /floor/ dev_dependencies: flutter_test: sdk: flutter floor_generator: git: url: https://github.com/vitusortner/floor.git path: /floor_generator/ build_runner: ^1.1.3 -
-
Make sure to import the following libraries.
import 'package:floor/floor.dart'; import 'package:path/path.dart'; import 'package:sqflite/sqflite.dart' as sqflite; -
Create an
Entity. It will represent a database table as well as the scaffold of your business object.@Entity()marks the class as a persistent class. It's required to add a primary key to your table. You can do so by adding the@PrimarKey()annotation to anintproperty.@Entity() class Person { @PrimaryKey() final int id; final String name; Person(this.id, this.name); } -
Create the
Database. This component is responsible for managing the access to the underlying SQLite database. It has to be an abstract class which extendsFloorDatabase. Furthermore, it's required to add@Database()to the signature of the class.This class contains the method signatures for querying the database which have to return a
Future. It, moreover, holds functionality for opening the database._$open()is a function that will get implemented by running the code generator. The warning, of it not being implemented, will go away then.-
You can define queries by adding the
@Queryannotation to a method. The SQL statement has to get added in parenthesis. The method must return aFutureof theEntityyou're querying for. -
@insertmarks a method as an insertion method.
@Database() abstract class AppDatabase extends FloorDatabase { static Future<AppDatabase> openDatabase() async => _$open(); @Query('SELECT * FROM Person') Future<List<Person>> findAllPersons(); @Query('SELECT * FROM Person WHERE id = :id') Future<Person> findPersonById(int id); @insert Future<void> insertPerson(Person person); } -
-
Add
part 'database.g.dart';beneath the imports of this file. It's important to note, that 'database' has to get exchanged with the name of the file the entity and database is defined in. In this case the file is nameddatabase.dart. -
Run the generator with
flutter packages pub run build_runner build. To automatically run it, whenever a file changes, useflutter packages pub run build_runner watch. -
Use the generated code.
final database = await AppDatabase.openDatabase(); final person = await database.findPersonById(1); await database.insertPerson(person);
For further examples take a look at the example and floor_test directories.
Querying #
Method signatures turn into query methods by adding the @Query() annotation with the query in parenthesis to them.
Be patient about the correctness of your SQL statements.
They are only partly validated while generating the code.
These queries have to return either a Future of an entity or void.
Returning Future<void> comes in handy whenever you want to delete the full content of a table.
@Query('SELECT * FROM Person WHERE id = :id')
Future<Person> findPersonById(int id);
@Query('SELECT * FROM Person WHERE id = :id AND name = :name')
Future<Person> findPersonByIdAndName(int id, String name);
@Query('SELECT * FROM Person')
Future<List<Person>> findAllPersons(); // select multiple items
@Query('DELETE FROM Person')
Future<void> deleteAllPersons(); // query without returning an entity
Persisting Data Changes #
Use the @insert, @update and @delete annotations for inserting and changing persistent data.
All these methods accept single or multiple entity instances.
-
Insert
@insertmarks a method as an insertion method. WHen using the capitalized@Insertyou can specify a conflict strategy. Else it just defaults to aborting the insert. These methods can return aFutureof eithervoid,intorList<int>.voidreturn nothingintreturn primary key of inserted itemList<int>return primary keys of inserted items
-
Update
@updatemarks a method as an update method. When using the capitalized@Updateyou can specify a conflict strategy. Else it just defaults to aborting the update. These methods can return aFutureof eithervoidorint.voidreturn nothingintreturn number of changed rows
-
Delete
@deletemarks a method as a deletion method. These methods can return aFutureof eithervoidorint.voidreturn nothingintreturn number of deleted rows
// examples of changing multiple items with return
@insert
Future<List<int>> insertPersons(List<Person> person);
@update
Future<int> updatePersons(List<Person> person);
@delete
Future<int> deletePersons(List<Person> person);
Transactions #
Whenever you want to perform some operations in a transaction you have to add the @transaction annotation to the method.
It's also required to add the async modifier. These methods can only return Future<void>.
@transaction
Future<void> replacePersons(List<Person> persons) async {
await deleteAllPersons();
await insertPersons(persons);
}
Entities #
An entity is a persistent class.
Floor automatically creates the mappings between the in-memory objects and database table rows.
It's possible to supply custom metadata to Floor by adding optional values to the Entity annotation.
It has the additional attribute of tableName which opens up the possibility to use a custom name for that specific entity instead of using the class name.
Another attribute foreignKeys allows to add foreign keys to the entity.
More information on how to use these can be found in the Foreign Keys section.
@PrimaryKey marks a property of a class as the primary key column.
This property has to be of type int.
The value can be automatically generated by SQLite when autoGenerate is enabled.
@ColumnInfo enables custom mapping of single table columns.
With the annotation it's possible to give columns a custom name and define if the column is able to store null.
@Entity(tableName: 'person')
class Person {
@PrimaryKey(autoGenerate: true)
final int id;
@ColumnInfo(name: 'custom_name', nullable: false)
final String name;
Person(this.id, this.name);
}
Foreign Keys #
Add a list of ForeignKeys to the Entity annotation of the referencing entity.
childColumns define the columns of the current entity, whereas parentColumns define the columns of the parent entity.
Foreign key actions can get triggered after defining them for the onUpdate and onDelete properties.
@Entity(
tableName: 'dog',
foreignKeys: [
ForeignKey(
childColumns: ['owner_id'],
parentColumns: ['id'],
entity: Person,
)
],
)
class Dog {
@PrimaryKey()
final int id;
final String name;
@ColumnInfo(name: 'owner_id')
final int ownerId;
Dog(this.id, this.name, this.ownerId);
}
Examples #
For further examples take a look at the example and floor_test directories.
Naming #
Floor - the bottom layer of a Room.
Bugs and Feedback #
For bugs, questions and discussions please use the Github Issues.
License #
Copyright 2019 Vitus Ortner
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.