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.

Entity DSL

エンティティ操作を行うためのDSL

概要

Entity DSLはエンティティのマッピング定義情報を基に以下のことを行います。

  • SELECT実行時に検索結果を返す前にエンティティのIDを用いた重複除去やエンティティの関連づけ
  • INSERT実行時にIDやタイムスタンプの生成
  • UPDATEやDELETEの実行時にバージョン番号を用いた楽観的排他制御

SELECT

SELECTクエリはEntityDslfromを呼び出して生成します。これが基本の形となります。

次のクエリはADDRESSテーブルを全件取得するSQLに対応します。

val query: Query<List<Address>> = EntityDsl.from(a)
/*
select t0_.ADDRESS_ID, t0_.STREET, t0_.VERSION from ADDRESS as t0_
*/

fromを呼び出した後、以下に説明するような関数をいくつか呼び出すことでクエリを組み立てます。

where

WHERE句を指定する場合はwhereを呼び出します。

val query: Query<List<Address>> = EntityDsl.from(a).where { a.addressId eq 1 }
/*
select t0_.ADDRESS_ID, t0_.STREET, t0_.VERSION from ADDRESS as t0_ where t0_.ADDRESS_ID = ?
*/

以下のドキュメントも参照ください。

innerJoin

INNER JOINを行う場合はinnerJoinを呼び出します。

val query: Query<List<Address>> = EntityDsl.from(a).innerJoin(e) { a.addressId eq e.addressId }
/*
select t0_.ADDRESS_ID, t0_.STREET, t0_.VERSION from ADDRESS as t0_ inner join EMPLOYEE as t1_ on (t0_.ADDRESS_ID = t1_.ADDRESS_ID)
*/

以下のドキュメントも参照ください。

leftJoin

LEFT OUTER JOINを行う場合はleftJoinを呼び出します。

val query: Query<List<Address>> = EntityDsl.from(a).leftJoin(e) { a.addressId eq e.addressId }
/*
select t0_.ADDRESS_ID, t0_.STREET, t0_.VERSION from ADDRESS as t0_ left outer join EMPLOYEE as t1_ on (t0_.ADDRESS_ID = t1_.ADDRESS_ID)
*/

以下のドキュメントも参照ください。

associate

エンティティ間の関連づけを行うには、innerJoinもしくはleftJoinを呼び出した後、同一のマッピング定義に対してassociateを呼び出します。

val query: Query<List<Employee>> = EntityDsl.from(e).innerJoin(a) {
    e.addressId eq a.addressId
}.associate(e, a) { employee, address ->
    employee.copy(address = address)
}
/*
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, t1_.ADDRESS_ID, t1_.STREET, t1_.VERSION from EMPLOYEE as t0_ inner join ADDRESS as t1_ on (t0_.ADDRESS_ID = t1_.ADDRESS_ID)
*/

forUpdate

FOR UPDATE句を指定する場合はforUpdateを呼び出します。

val query: Query<List<Address>> = EntityDsl.from(a).where { a.addressId eq 1 }.forUpdate()
/*
select t0_.ADDRESS_ID, t0_.STREET, t0_.VERSION from ADDRESS as t0_ where t0_.ADDRESS_ID = ? for update
 */

orderBy

ORDER BY句を指定する場合はorderByを呼び出します。

val query: Query<List<Adress>> = EntityDsl.from(a).orderBy(a.addressId)
/*
select t0_.ADDRESS_ID, t0_.STREET, t0_.VERSION from ADDRESS as t0_ order by t0_.ADDRESS_ID asc
*/

デフォルトでは昇順ですが降順を指定する場合はカラムをorderByに渡す前にカラムに対してdescを呼び出します。 また、昇順を表すascを明示的に呼び出すことやカラムを複数指定することもできます。

val query: Query<List<Adress>> = EntityDsl.from(a).orderBy(a.addressId.desc(), a.street.asc())
/*
select t0_.ADDRESS_ID, t0_.STREET, t0_.VERSION from ADDRESS as t0_ order by t0_.ADDRESS_ID desc, t0_.STREET asc
*/

offset, limit

指定した位置から一部の行を取り出すにはoffsetlimitを呼び出します。

val query: Query<List<Adress>> = EntityDsl.from(a).orderBy(a.addressId).offset(10).limit(3)
/*
select t0_.ADDRESS_ID, t0_.STREET, t0_.VERSION from ADDRESS as t0_ order by t0_.ADDRESS_ID asc offset ? rows fetch first ? rows only
*/

first

1件を返却するクエリであることを示すには最後にfirstを呼び出します。

val query: Query<Address> = EntityDsl.from(a).where { a.addressId eq 1 }.first()
/*
select t0_.ADDRESS_ID, t0_.STREET, t0_.VERSION from ADDRESS as t0_ where t0_.ADDRESS_ID = ?
*/

firstOrNull

1件もしくは0件の場合にnullを返却するクエリであることを示すには最後にfirstOrNullを呼び出します。

val query: Query<Address?> = EntityDsl.from(a).where { a.addressId eq 1 }.firstOrNull()
/*
select t0_.ADDRESS_ID, t0_.STREET, t0_.VERSION from ADDRESS as t0_ where t0_.ADDRESS_ID = ?
*/

INSERT

INSERTクエリはEntityDslinsertとそれに続く関数を呼び出して生成します。

single

1件を追加するにはsingleを呼び出します。

val address: Address = ..
val query: Query<Address> = EntityDsl.insert(a).single(address)
/*
insert into ADDRESS (ADDRESS_ID, STREET, VERSION) values (?, ?, ?)
*/

このクエリを実行した場合の戻り値は追加されたデータを表す新しいエンティティです。 つまり、IDやタイムスタンプが自動生成される設定をしている場合、生成されたIDやタイムスタンプがセットされたエンティティが返されます。

multiple

1文で複数件を追加するにはmultipleを呼び出します。

val query: Query<List<Address>> = EntityDsl.insert(a).multiple(
    Address(16, "STREET 16", 0),
    Address(17, "STREET 17", 0),
    Address(18, "STREET 18", 0)
)
/*
insert into ADDRESS (ADDRESS_ID, STREET, VERSION) values (?, ?, ?), (?, ?, ?), (?, ?, ?)
*/

このクエリを実行した場合の戻り値は追加されたデータを表す新しいエンティティです。 つまり、IDやタイムスタンプが自動生成される設定をしている場合、生成されたIDやタイムスタンプがセットされたエンティティが返されます。

batch

バッチで複数件を追加するにはbatchを呼び出します。

val query: Query<List<Address>> = EntityDsl.insert(a).batch(
    Address(16, "STREET 16", 0),
    Address(17, "STREET 17", 0),
    Address(18, "STREET 18", 0)
)
/*
insert into ADDRESS (ADDRESS_ID, STREET, VERSION) values (?, ?, ?)
insert into ADDRESS (ADDRESS_ID, STREET, VERSION) values (?, ?, ?)
insert into ADDRESS (ADDRESS_ID, STREET, VERSION) values (?, ?, ?)
*/

このクエリを実行した場合の戻り値は追加されたデータを表す新しいエンティティです。 つまり、IDやタイムスタンプが自動生成される設定をしている場合、生成されたIDやタイムスタンプがセットされたエンティティが返されます。

onDuplicateKeyIgnore

onDuplicateKeyIgnoreを呼び出すことで値が重複した場合のエラーを無視できます。

val address: Address = ..
val query: Query<Int> = EntityDsl.insert(a).onDuplicateKeyIgnore().single(address)

このクエリを実行した場合の戻り値はドライバの返す値です。

上記クエリに対応するSQLはどのDialectを使うかで異なります。 例えば、MariaDBのDialectを使う場合は次のようなSQLになります。

insert ignore into ADDRESS (ADDRESS_ID, STREET, VERSION) values (?, ?, ?)

PostgreSQLのDialectを使う場合は次のようなSQLになります。

insert into ADDRESS as t0_ (ADDRESS_ID, STREET, VERSION) values (?, ?, ?) on conflict (ADDRESS_ID) do nothing

onDuplicateKeyUpdate

onDuplicateKeyIgnoreを呼び出すことで値が重複した場合にUPDATEを実行できます。

val department: Department = ..
val query: Query<Int> = EntityDsl.insert(d).onDuplicateKeyUpdate().single(department)

このクエリを実行した場合の戻り値はドライバの返す値です。

上記クエリに対応するSQLはどのDialectを使うかで異なります。 例えば、MariaDBのDialectを使う場合は次のようなSQLになります。

insert into DEPARTMENT (DEPARTMENT_ID, DEPARTMENT_NO, DEPARTMENT_NAME, LOCATION, VERSION) values (?, ?, ?, ?, ?) on duplicate key update DEPARTMENT_NO = values(DEPARTMENT_NO), DEPARTMENT_NAME = values(DEPARTMENT_NAME), LOCATION = values(LOCATION), VERSION = values(VERSION)

PostgreSQLのDialectを使う場合は次のようなSQLになります。

insert into DEPARTMENT as t0_ (DEPARTMENT_ID, DEPARTMENT_NO, DEPARTMENT_NAME, LOCATION, VERSION) values (?, ?, ?, ?, ?) on conflict (DEPARTMENT_ID) do update set DEPARTMENT_NO = excluded.DEPARTMENT_NO, DEPARTMENT_NAME = excluded.DEPARTMENT_NAME, LOCATION = excluded.LOCATION, VERSION = excluded.VERSION

UPDATE

UPDATEクエリはEntityDslupdateとそれに続く関数を呼び出して生成します。

single

1件を更新するにはsingleを呼び出します。

val address: Address = ..
val query: Query<Address> = EntityDsl.update(a).single(address)
/*
update ADDRESS set STREET = ?, VERSION = ? + 1 where ADDRESS_ID = ? and VERSION = ?
*/

batch

バッチで複数件を更新するにはbatchを呼び出します。

val address1: Address = ..
val address2: Address = ..
val address3: Address = ..
val query: Query<List<Address>> = EntityDsl.update(a).batch(address1, address2, address3)
/*
update ADDRESS set STREET = ?, VERSION = ? + 1 where ADDRESS_ID = ? and VERSION = ?
update ADDRESS set STREET = ?, VERSION = ? + 1 where ADDRESS_ID = ? and VERSION = ?
update ADDRESS set STREET = ?, VERSION = ? + 1 where ADDRESS_ID = ? and VERSION = ?
*/

DELETE

DELETEクエリはEntityDsldeleteとそれに続く関数を呼び出して生成します。

single

1件を削除するにはsingleを呼び出します。

val address: Address = ..
val query: Query<Unit> = EntityDsl.delete(a).single(address)
/*
delete from ADDRESS as t0_ where t0_.ADDRESS_ID = ? and t0_.VERSION = ?
*/

batch

バッチで複数件を削除するにはbatchを呼び出します。

val address1: Address = ..
val address2: Address = ..
val address3: Address = ..
val query: Query<Unit> = EntityDsl.delete(a).batch(address1, address2, address3)
/*
delete from ADDRESS as t0_ where t0_.ADDRESS_ID = ? and t0_.VERSION = ?
delete from ADDRESS as t0_ where t0_.ADDRESS_ID = ? and t0_.VERSION = ?
delete from ADDRESS as t0_ where t0_.ADDRESS_ID = ? and t0_.VERSION = ?
*/
最終更新 August 15, 2021 : Adjust heading IDs (a73516d)