前提
言語はkotlin
DBはPostgres
org.jetbrains.exposedの0.38.2を利用。
エンティティ周りのクラス構成についてはこちらの記事のものを利用してますのでこの機会にぜひこちらの記事もよろしくお願いします
https://qiita.com/yuya_sega/items/0d7cb7ae7ce531fb9eba
import org.jetbrains.exposed.dao.id.IntIdTable
import org.jetbrains.exposed.sql.jodatime.date
import org.jetbrains.exposed.sql.jodatime.datetime
object Users: IntIdTable("users") {
var name = varchar("name", 50)
var address = varchar("address", 255).nullable()
var isActive = bool("is_active").default(false)
var enteredOn = date("entered_on")
var createdAt = datetime("created_at")
}
import org.jetbrains.exposed.dao.id.IntIdTable
object Orders: IntIdTable("orders") {
var user = reference("user_id", Users)
var code = integer("code")
}
import org.jetbrains.exposed.dao.IntEntity
import org.jetbrains.exposed.dao.IntEntityClass
import org.jetbrains.exposed.dao.id.EntityID
class User(
id: EntityID<Int>
): IntEntity(id) {
companion object: IntEntityClass<User>(Users)
var name by Users.name
var address by Users.address
var isActive by Users.isActive
var enteredOn by Users.enteredOn
var createdAt by Users.createdAt
}
import org.jetbrains.exposed.dao.IntEntity
import org.jetbrains.exposed.dao.IntEntityClass
import org.jetbrains.exposed.dao.id.EntityID
class Order(
id: EntityID<Int>
): IntEntity(id) {
companion object: IntEntityClass<Order>(Orders)
var user by User referencedOn Orders.user
var code by Orders.code
}
select
1件引き
// primary keyによる1件引き
val user: User? = User.findById(1)
// その他キーによる1件引き
val user: User? = User.find {
Users.name eq "テスト太郎"
}.singleOrNull()
複数件引き
// 全件引き
User.all()
// List<User>で取るにはtoListします
User.all().toList()
// 条件の指定方法は1件引きと同じ
User.find{
Users.name eq "テスト太郎"
}.toList()
insert
// DAOパターン
User.new {
this.name = "テスト太郎"
this.enteredOn = org.joda.time.DateTime.now()
}
// DSL
Users.insert {
it[Users.name] = "テスト太郎"
it[Users.enteredOn] = org.joda.time.DateTime.now()
} get Users.id
update
// 事前準備
var user = User.new {
this.name = "テスト太郎"
this.enteredOn = org.joda.time.DateTime.now()
}
// DAO update
user = user.also {
it.name = "テスト次郎"
}
// DSL update
Users.update({ Users.id eq user.id}) {
it[Users.name] = "テスト次郎"
}
delete
User.findById(1).delete()
inner join
join先のデータをwhere条件に指定したいときに利用しました
Order.wrapRows(
Orders.innerJoin(Users).select {
Orders.code eq "test"
}
)
.with(Order::user)
left join
inner joinと書き方変わらないです
Order.wrapRows(
Orders.leftJoin(Users).select {
Orders.code eq "test"
}
)
.with(Order::user)
referencedOnをメンバとして持っている場合のjoin
withを使わない場合、フィールドアクセス時にSQLが実行されるのでパフォーマンス意識する場合はwith使ってあらかじめデータ取得しておくことをおすすめします
Order.find{
Orders.code eq "test"
}
.with(Order::user)
and
val param: Op<Boolean> = Op.build {
(User.name eq "テスト太郎") and
(User.isActive eq true)
}
User.find(param)
or
val param: Op<Boolean> = Op.build {
(User.name eq "テスト太郎") or
(User.isActive eq true)
}
User.find(param)
ちなみにandとorの混合はこんなふうに書きました
val param: Op<Boolean> = Op.build {
(User.name eq "テスト太郎") and
Op.build {(User.isActive eq true) or (User.address.isNull())}
}
User.find(param)
in
val names: List<String> = listOf("テスト太郎", "テスト次郎", "テスト三郎")
User.find {
Users.name.inList(names)
}
lessEq / greaterEq
val enteredOn = org.joda.time.DateTime.now()
// greaterEq
User.find {
Users.enteredOn greaterEq enteredOn
}
// lessEq
User.find {
Users.enteredOn lessEq enteredOn
}
is null / is not null
// isNull
User.find {
Users.address.isNull()
}
// isNotNull
User.find {
Users.address.isNotNull()
}
order by
User.all().orderBy(Users.id to SortOrder.ASC)
limit
User.all().limit(1)