DBFlow is a convenient ORM Android database framework developed based on annotation processors. This library simplifies a lot of redundant code and provides a user-friendly API for handling interactions with the database, allowing developers to focus on app development. Below, we will learn about the usage of the DBFlow database framework from the following aspects:
- Advantages of DBFlow
- Configuring DBFlow
- Creating a Database
- Creating Tables
- Inserting Data
- Deleting Data
- Updating Data
- Querying Data
- Case Study
Advantages of DBFlow#
DBFlow draws on features from other excellent database frameworks. Here are the advantages of DBFlow:
- Extensibility: There are no restrictions on subclasses of table classes; they can be ordinary JavaBeans. For convenience, it is recommended that table classes inherit from the BaseModel class. You can extend non-model classes from different packages and use them as database tables. Additionally, you can include subclasses of other tables in @Column, and they can be located in different packages.
- Speed: This library is generated based on Java's annotation processor, which has almost no impact on runtime performance (reflection is only used for generating the database module). It saves time in generating boilerplate code, supports model caching (multi-primary key models), and is faster than native SQLite when possible. It supports lazy loading, @ForeignKey, @OneToMany, etc., making queries more efficient.
- SQLite Query Flow: DBFlow's queries are as close as possible to native SQLite queries, such as:
select(name, screenSize).from(Android.class).where(name.is("Nexus 5x")).and(version.is(6.0)).querySingle()
- Open Source: DBFlow is open source, and the open-source address is: Github
- Robustness: Supports Trigger, ModelView, Index, Migration, and built-in methods for managing databases. Additionally, it supports SQLCipher, RXJava, etc.
- Multiple Databases, Multiple Modules: Seamlessly supports multiple database files and database models in other dependencies using DBFlow.
- Built On SQLite: SQLite is the most widely used database engine in the world and is not limited to any specific platform.
Configuring DBFlow#
Since DBFlow is not officially released yet, you need to configure the following in your project's build.gradle file:
allprojects {
repositories {
jcenter()
maven { url "https://jitpack.io" }
}
}
Then, add dependencies in the corresponding module's build.gradle file as follows:
// For convenience, you can use the def keyword to define version numbers
def dbFlow_version = "4.2.4"
dependencies {
//...
annotationProcessor "com.github.Raizlabs.DBFlow:dbflow-processor:${dbFlow_version}"
compile "com.github.Raizlabs.DBFlow:dbflow-core:${dbFlow_version}"
compile "com.github.Raizlabs.DBFlow:dbflow:${dbFlow_version}"
}
The dependencies in the above code are only for Java. If you want to use Kotlin, RxJava, etc., you need to configure the corresponding dependencies.
Note: When upgrading to a new version of DBFlow, be sure to remove the old version dependencies, as the annotation processors for the new and old versions may differ. If the old version is not removed, the following error will occur:
java.lang.NoSuchMethodError: com.raizlabs.android.dbflow.annotation.Table.tableName()Ljava/lang/String
Then, customize the Application and initialize DBFlow in the corresponding onCreate() method as follows:
/**
* Custom Application
* @author jzman
* create at 2018/4/16 0016 17:28
*/
public class MyApplication extends Application{
@Override
public void onCreate() {
super.onCreate();
// Initialize DBFlow
FlowManager.init(new FlowConfig.Builder(this).build());
// Set logging level
FlowLog.setMinimumLoggingLevel(FlowLog.Level.V);
}
}
Finally, use the customized Application in the AndroidManifest.xml file as follows:
<application
android:name=".app.MyApplication"
// ...
</application>
At this point, DBFlow has been introduced into the current project.
Creating a Database#
Create a class and use the @Database annotation to define your own database. This class should define the database name and version, as follows:
/**
* MyDatabase
* @author jzman
* create at 2018/4/17 0017 9:08
*/
@Database(name = MyDatabase.NAME, version = MyDatabase.VERSION)
public class MyDatabase {
// Database name
public static final String NAME = "MyDatabase";
// Database version number
public static final int VERSION = 1;
}
Note: If you need to modify the structure of any table in the future, be sure to change the version number to avoid conflicts with the old version of the database, and ensure that the version number only increases.
Creating Tables#
Once the database is created, you can create tables. The model class for the table generally needs to inherit from BaseModel and add the @Column annotation to each field in the model class. This annotation maps the fields of the model class to the corresponding columns in the table. Define a table as follows:
/**
* NoteTable.java
* @author jzman
* create at 2018/4/17 0017 9:54
*/
@Table(database = MyDatabase.class)
public class NoteTable extends BaseModel {
@Column
@PrimaryKey
int id;
@Column
private String title;
@Column
private String date;
@Column
private String content;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
Note: At least one field must be defined as the primary key in a table. If a field in the model class is private, you must define the corresponding getter and setter methods; otherwise, the table creation will fail. The naming of the table should use camel case, or you may encounter issues like:
java.lang.IllegalArgumentException: expected type but was null
Inserting Data#
There are two common ways to insert data using DBFlow, as follows:
- model.insert()
- SQLite.insert()
The former is used for inserting a single model class object. After creating the specific object, you can call model.insert() to insert the corresponding record for that object. The latter uses SQLite Wrapper Language to insert data, similar to the native insert statement, and supports inserting multiple columns of data, making it quite convenient. Refer to the following example:
/**
* Insert data
* @param model
*/
public void insertData(NoteBean model){
//1. model.insert()
model.setTitle("title");
model.setDate("2018-04-17");
model.setContent("content");
model.insert();
//2. SQLite.insert()
SQLite.insert(NoteBean.class)
.columns(NoteBean_Table.title, NoteBean_Table.date, NoteBean_Table.content)
.values("title", "2018-04-17", "content")
.execute();
}
Deleting Data#
There are two common ways to delete data using DBFlow, as follows:
- model.delete(): Delete a specific record
- SQLite.delete(): Delete based on conditions
The former is used for deleting a single model class object. After creating the specific object, you can call model.delete() to delete the corresponding record for that object. The latter uses SQLite Wrapper Language to conditionally delete data, similar to the native delete statement, and is quite convenient. Refer to the following example:
/**
* Delete data
* @param model
*/
public void deleteData(NoteBean model){
//1. model.delete()
model.delete();
//2. SQLite.delete()
SQLite.delete(NoteBean.class)
.where(NoteBean_Table.title.is("title"))
.and(NoteBean_Table.id.is(10))
.async()
.execute();
// Delete the entire table
Delete.table(NoteBean.class);
// Delete multiple tables
Delete.table(NoteBean.class, NoteBean1.class);
}
Updating Data#
There are two common ways to update data using DBFlow, as follows:
- model.update(): Update a specific record
- SQLite.update(): Update a specific record based on conditions
The former is used for updating a single model class object. After creating the specific object, you can call model.update() to update the corresponding record for that object. The latter uses SQLite Wrapper Language to conditionally update data, similar to the native update statement, and is quite convenient. Refer to the following example:
/**
* Update data
* @param model
*/
public void updateData(NoteBean model) {
//1. model.update()
model.update();
//2. SQLite.update()
SQLite.update(NoteBean.class)
.set(NoteBean_Table.title.eq("title"),
NoteBean_Table.content.eq("content"))
.where(NoteBean_Table.id.is(10))
.async()
.execute();
}
Querying Data#
Querying uses the SQLite.select() method, and there are many keywords that can be used as conditions. Here is a common query example for developers:
/**
* Query data
*/
public List<NoteBean> queryData(){
// Query based on conditions
List<NoteBean> noteBeans = SQLite.select()
.from(NoteBean.class)
.where(NoteBean_Table.title.is("title"))
.queryList();
return noteBeans;
}
Note: For insert and update operations, you can use the model.save() method.
Case Study#
The above text introduced the configuration of DBFlow and basic operations such as insert, delete, update, and query. DBFlow also has other more advanced usages, such as using Transactions for safe data operations. Below is a simple case study to conclude the learning of DBFlow, with the specific effect as follows:
For more knowledge about DBFlow, please refer to DBFlow's GitBook.