4.5 KiB
Overview
The DAO (Data Access Object) API of Exposed, is similar to ORM frameworks like Hibernate with specific Kotlin API.
A DB table is represented by an object inherited from org.jetbrains.exposed.sql.Table like that:
object StarWarsFilms : Table() {
val id: Column<Int> = integer("id").autoIncrement().primaryKey()
val sequelId: Column<Int> = integer("sequel_id").uniqueIndex()
val name: Column<String> = varchar("name", 50)
val director: Column<String> = varchar("director", 50)
}
Tables that contains Int id with the name id can be declared like that:
object StarWarsFilms : IntIdTable() {
val sequelId: Column<Int> = integer("sequel_id").uniqueIndex()
val name: Column<String> = varchar("name", 50)
val director: Column<String> = varchar("director", 50)
}
Note that these Column types will be defined automatically, so you can also just leave them away. This would produce the same result as the example above:
object StarWarsFilms : IntIdTable() {
val sequelId = integer("sequel_id").uniqueIndex()
val name = varchar("name", 50)
val director = varchar("director", 50)
}
An entity instance or a row in the table is defined as a class instance:
class StarWarsFilm(id: EntityID<Int>) : IntEntity(id) {
companion object : IntEntityClass<StarWarsFilm>(StarWarsFilms)
var sequelId by StarWarsFilms.sequelId
var name by StarWarsFilms.name
var director by StarWarsFilms.director
}
Basic CRUD operations
Create
val movie = StarWarsFilm.new {
name = "The Last Jedi"
sequelId = 8
director = "Rian Johnson"
}
Read
To get entities use one of the following
val movies = StarWarsFilm.all()
val movies = StarWarsFilm.find {StarWarsFilms.sequelId eq 8}
val movie = StarWarsFilm.findById(5)
- For a list of avaialable predicates see DSL Where expression.
Read a value from a property similarly to any property in a Kotlin class:
val name = movie.name
Update
Update a value of a property similarly to any property in a Kotlin class:
movie.name = "Episode VIII – The Last Jedi"
Delete
movie.delete()
Referencing
Simple reference
Let's say you have this table:
object Users: IntIdTable() {
val name = varchar("name", 50)
}
class User(id: EntityID<Int>): IntEntity(id) {
companion object : IntEntityClass<User>(Users)
var name by Users.name
}
And now you want to add a table referencing this table (and other tables!):
object UserRatings: IntIdTable() {
val value = long("value")
val film = reference("film", StarWarsFilms)
val user = reference("user", Users)
}
class UserRating(id: EntityID<Int>): IntEntity(id) {
companion object : IntEntityClass<UserRating>(UserRatings)
var value by UserRatings.value
var film by StarWarsFilm referencedOn UserRatings.film // use referencedOn for normal references
var user by User referencedOn UserRatings.user
}
Now you can get the film for a rating in the same way you would get any other field:
filmRating.film // returns a StarWarsFilm object
Now if you wanted to get all the ratings for a film, you could do that by using the FilmRating.find function, but what is much easier is to just add a referrersOn field to the StarWarsFilm class:
class StarWarsFilm(id: EntityID<Int>) : IntEntity(id) {
companion object : IntEntityClass<StarWarsFilm>(StarWarsFilms)
...
val ratings by UserRating referrersOn UserRatings.film // make sure to use val and backReferencedOn
...
}
You can call:
movie.ratings // returns all UserRating objects with this movie as film
Optional reference
You can also add an optional reference:
object UserRatings: IntIdTable() {
...
val secondUser = reference("second_user", Users).nullable() // this reference is nullable!
...
}
class UserRating(id: EntityID<Int>): IntEntity(id) {
companion object : IntEntityClass<UserRating>(UserRatings)
...
var secondUser by User optionalReferencedOn UserRatings.secondUser // use optionalReferencedOn for nullable references
...
}
Now secondUser will be a nullable field.
Of course you can still use referrersOn.