Kotlin Support + Extensions
DBFlow supports Kotlin out of the box and is fairly easily to use and implement.
To add useful Kotlin-specific extensions:
dependencies {
compile "com.github.Raizlabs.DBFlow:dbflow-kotlinextensions:${dbflow_version}@aar"
}
We also support kotlin extensions for RX 1 + 2!
Classes
DBFlow Classes are beautifully concise to write:
@Table(database = KotlinDatabase::class)
class Person(@PrimaryKey var id: Int = 0, @Column var name: String? = null)
Also data
classes are supported.
@Table(database = KotlinTestDatabase::class)
data class Car(@PrimaryKey var id: Int = 0, @Column var name: String? = null)
In 4.0.0+, DBFlow contains a few extensions for Kotlin models which enable you
to keep your models acting like BaseModel
, but do not have to explicitly extend
the class!
car.save() // extension method, optional databaseWrapper parameter.
car.insert()
car.update()
car.delete()
car.exists()
Null Safety
DBFlow reflects the nullability on fields defined in their classes. If you define a
@Column
as not null, it will not assign a null value to that field in the generated java.
Query LINQ Syntax
Kotlin has nice support for custim infix
operators. Using this we can convert a regular, Plain old java query into a C#-like LINQ syntax.
java:
List<Result> = SQLite.select()
.from(Result.class)
.where(Result_Table.column.eq(6))
.and(Result_Table.column2.in("5", "6", "9")).queryList()
kotlin:
val results = (select
from Result::class
where (column eq 6)
and (column2 `in`("5", "6", "9"))
groupBy column).list
// can call .result for single result
// .hasData if it has results
// .statement for a compiled statement
Enabling us to write code that is closer in syntax to SQLite!
This supported for almost any SQLite operator that this library provides including:
Select
Insert
Update
Delete
Async Operations:
With extensions we also support async
operations on queries:
// easy async list query
(select
from Result::class
where (column eq 6))
.async list { transaction, list ->
// do something here
updateUI(list)
}
// easy single result query
(select
from Result::class
where (column eq 6))
.async result { transaction, model ->
// do something here
updateUI(model)
}
val model = Result()
model.async save {
// completed, now do something with model
}
Property Extensions
With Kotlin, we can define extension methods on pretty much any class.
With this, we added methods to easily create IProperty
from anything to make
queries a little more streamlined. In this query, we also make use of the extension
method for from
to streamline the query even more.
var query = (select
from TestModel::class
where (5.property lessThan column)
and (clause(date.property between start_date)
and(end_date)))
Query Extensions
We can easily create nested Operator
into OperatorGroup
also fairly easily, also
other, random extensions:
select from SomeTable::class where (name.eq("name") and id.eq(0))
"name".op<String>() collate NOCASE
"name".nameAlias
"name".nameAlias `as` "My Name"
// query sugar
select from SomeTable::class where (name eq "name") or (id eq 0)
Database Extensions
Process Models Asynchronously
In Java, we need to write something of the fashion:
List<TestModel> items = SQLite.select()
.from(TestModel.class)
.queryList();
database.beginTransactionAsync(new ProcessModelTransaction.Builder<>(
new ProcessModel<TestModel>() {
@Override
public void processModel(TestModel model, DatabaseWrapper database) {
}
})
.success(successCallback)
.error(errorCallback).build()
.execute();
In Kotlin, we can use a combo of DSL and extension methods to:
var items = (select from TestModel1::class).list
// easily delete all these items.
items.processInTransactionAsync { it, databaseWrapper -> it.delete(databaseWrapper) }
// easily delete all these items with success
items.processInTransactionAsync({ it, databaseWrapper -> it.delete(databaseWrapper) },
success = { transaction ->
// do something here
})
// delete with all callbacks
items.processInTransactionAsync({ it, databaseWrapper -> it.delete(databaseWrapper) },
success = { transaction ->
// do something here
},
error = { transaction, throwable ->
})
The extension method on Collection<T>
allows you to perform this on all
collections from your Table!
If you wish to easily do them synchronously then use:
items.processInTransaction { it, databaseWrapper -> it.delete(databaseWrapper) }
Class Extensions
If you need access to the Database, ModelAdapter, etc for a specific class you can now use the following (and more) inline reified global functions for easy access!
database<MyDatabase>()
databaseForTable<TestModel>()
writableDatabaseForTable<TestModel>()
tableName<TestModel>()
modelAdapter<TestModel>()
Which under-the-hood call their corresponding FlowManager
methods.