Version v0.18 of the documentation is no longer actively maintained. The site that you are currently viewing is an archived snapshot. For up-to-date documentation, see the latest version.
Introduction
概要
Komapperではクエリの構築と実行は分離されています。 クエリの構築は各種のDSLが担い、実行はJDBCやR2DBCを表す Database インスタンスが担います。
// create a query
val query: Query<List<Address>> = EntityDsl.from(a)
// run the query
val result: List<Address> = db.runQuery { query }
このページではクエリとその構成要素である宣言について説明します。
クエリの構築を担うDSLについては専用のページを参照ください。
宣言の構成要素である式については専用のページを参照ください。
クエリ
Komapperにおけるクエリは以下のクラスのいずれかもしくは両方で表現されます。
org.komapper.core.dsl.query.Query<T>Databaseインスタンスを介して実行するとデータベースにアクセスしT型の値を返すクエリ。org.komapper.core.dsl.query.FlowQuery<T>Databaseインスタンスを介して実行するとkotlinx.coroutines.flow.Flow<T>型の値を返すクエリ。データベースアクセスはFlowがcollectされたときに初めて行われます。
Note
FlowQuery<T>を構築できるDSLはSQL DSLのみであり、R2dbcDatabaseインスタンスによってのみ実行可能です。
クエリの合成
クエリは合成できます。
plus
+演算子を使うと、まとめて実行して最後の結果を返すクエリを構築できます。
val q1: Query<Address> = EntityDsl.insert(a).single(Address(16, "STREET 16", 0))
val q2: Query<Address> = EntityDsl.insert(a).single(Address(17, "STREET 17", 0))
val q3: Query<List<Address>> = EntityDsl.from(a).where { a.addressId inList listOf(16, 17) }
val query: Query<List<Address>> = q1 + q2 + q3
val list: List<Address> = db.runQuery { query }
/*
insert into ADDRESS (ADDRESS_ID, STREET, VERSION) values (?, ?, ?)
insert into ADDRESS (ADDRESS_ID, STREET, VERSION) values (?, ?, ?)
select t0_.ADDRESS_ID, t0_.STREET, t0_.VERSION from ADDRESS as t0_ where t0_.ADDRESS_ID in (?, ?)
*/
flatMap
flatMap関数を使うと、1番目のクエリの実行結果を受け取って2番目のクエリを実行し2番目の結果を返すクエリを構築できます。
val q1: Query<Address> = EntityDsl.insert(a).single(Address(16, "STREET 16", 0)) // 1st query
val query: Query<List<Employee>> = q1.flatMap { newAddress ->
EntityDsl.from(e).where { e.addressId less newAddress.addressId } // 2nd query
}
val list: List<Employee> = db.runQuery { query }
/*
insert into ADDRESS (ADDRESS_ID, STREET, VERSION) values (?, ?, ?)
select t0_.EMPLOYEE_ID, t0_.EMPLOYEE_NO, t0_.EMPLOYEE_NAME, t0_.MANAGER_ID, t0_.HIREDATE, t0_.SALARY, t0_.DEPARTMENT_ID, t0_.ADDRESS_ID, t0_.VERSION from EMPLOYEE as t0_ where t0_.ADDRESS_ID < ?
*/
flatZip
flatZip関数を使うと、1番目のクエリの実行結果を受け取って2番目のクエリを実行し1番目と2番目の結果をPair型で返すクエリを構築できます。
val q1: Query<Address> = EntityDsl.insert(a).single(Address(16, "STREET 16", 0)) // 1st query
val query: Query<Pair<Address, List<Employee>>> = q1.flatZip { newAddress ->
EntityDsl.from(e).where { e.addressId less newAddress.addressId } // 2nd query
}
val pair: Pair<Address, List<Employee>> = db.runQuery { query }
/*
insert into ADDRESS (ADDRESS_ID, STREET, VERSION) values (?, ?, ?)
select t0_.EMPLOYEE_ID, t0_.EMPLOYEE_NO, t0_.EMPLOYEE_NAME, t0_.MANAGER_ID, t0_.HIREDATE, t0_.SALARY, t0_.DEPARTMENT_ID, t0_.ADDRESS_ID, t0_.VERSION from EMPLOYEE as t0_ where t0_.ADDRESS_ID < ?
*/
宣言
Entity DSLとSQL DSLでは、例えばwhere関数やhaving関数に検索条件を表すラムダ式を渡しますが、
Komapperではこれらのラムダ式のことを宣言と呼びます。
宣言には以下のものがあります。
- Having宣言 -
HavingDeclaration - On宣言 -
OnDeclaration - Set宣言 -
SetDeclaration - Values宣言 -
ValuesDeclaration - When宣言 -
WhenDeclaration - Where宣言 -
WhereDeclaration
宣言の合成
宣言は合成できます。
plus
+演算子を使うと、被演算子の宣言内部に持つ式を順番に実行するような新たな宣言を構築できます。
val w1: WhereDeclaration = {
a.addressId eq 1
}
val w2: WhereDeclaration = {
a.version eq 1
}
val w3: WhereDeclaration = w1 + w2 // +演算子の利用
val query: Query<List<Address>> = EntityDsl.from(a).where(w3)
val list: List<Address> = db.runQuery { query }
/*
select t0_.ADDRESS_ID, t0_.STREET, t0_.VERSION from ADDRESS as t0_ where t0_.ADDRESS_ID = ? and t0_.VERSION = ?
*/
+演算子はすべての宣言で利用できます。
and
and関数を使うと、宣言をand演算子で連結する新たな宣言を構築できます。
val w1: WhereDeclaration = {
a.addressId eq 1
}
val w2: WhereDeclaration = {
a.version eq 1
or { a.version eq 2 }
}
val w3: WhereDeclaration = w1 and w2 // and関数の利用
val query: Query<List<Address>> = EntityDsl.from(a).where(w3)
val list: List<Address> = db.runQuery { query }
/*
select t0_.ADDRESS_ID, t0_.STREET, t0_.VERSION from ADDRESS as t0_ where t0_.ADDRESS_ID = ? and (t0_.VERSION = ? or (t0_.VERSION = ?))
*/
and関数は、Having宣言、When宣言、Where宣言に対して適用できます。
or
or関数を使うと、宣言をor演算子で連結する新たな宣言を構築できます。
val w1: WhereDeclaration = {
a.addressId eq 1
}
val w2: WhereDeclaration = {
a.version eq 1
a.street eq "STREET 1"
}
val w3: WhereDeclaration = w1 or w2 // or関数の利用
val query: Query<List<Address>> = EntityDsl.from(a).where(w3)
val list: List<Address> = db.runQuery { query }
/*
select t0_.ADDRESS_ID, t0_.STREET, t0_.VERSION from ADDRESS as t0_ where t0_.ADDRESS_ID = ? or (t0_.VERSION = ? and t0_.STREET = ?)
*/
or関数は、Having宣言、When宣言、Where宣言に対して適用できます。