insert(entity)

概要

基本概念

Entityをもとに 一件登録 をします。

主キー(PK)の値が自動採番される設定になっている場合(シーケンスや Identity)は、主キーの値を設定せずに登録し、登録処理後の Entity から採番された主キーの値が取得できます。

会話上では、いんさーと と表現します。

実装方法

実装の流れ

Behaviorの insert() を呼び出し、Entityを指定します。

e.g. insert()の実装手順 (Eclipseでコード補完) {MEMBER} @Java
Member member = new Member();
//member.setMemberId(1); // 自動採番の場合は不要
member.setMemberName("Stojkovic");
member.setMemberAccount("Pixy");
member.setMemberStatusCode_Provisional();

member.set... // null で登録する場合は設定は不要

//member.setRegisterUser(user); // 共通カラムは自動設定(設定が有効なら)
//member.setRegister...
//member.setVersionNo(versionNo); // バージョン番号は自動で初期値に

memberBhv.in // .in と打って enter
--
memberBhv.insert(member);

Integer memberId = member.getMemberId(); // 自動採番の場合は採番値が取得できる

メソッド仕様

引数

該当のBehaviorに対応するテーブルのEntityとなります。

nullを指定した場合は例外発生します。

戻り値

void です。

例外

一意制約違反があった場合
org.seasar.dbflute.exception.EntityAlreadyExistsException
DBFluteで正式サポートしていない DBMS では、別の例外(SQLFailureException)の可能性があります。

自動採番処理の自動化

主キーに対して自動採番の設定がされている場合は、主キーの値の指定は不要です。 シーケンスの場合は、PK値が設定されていればその値で登録され、設定されていなければシーケンスで自動採番されます。Identity の場合は、PK値の設定有無に関わらず必ず Identity で自動採番されます。

採番された値は、登録処理後の Entity から取得することができます。ただし、DBMS によっては状況次第で採番値の取得ができないことがあります。例えば MySQL では、トランザクションでない insert 処理では Identity で採番した値を取得することができません。

Identityカラムに対するアプリで明示的に指定した値での登録は、varyingInsert(entity, option) にてオプション指定で実現できます(@since 0.9.7.8)。 ただし、実際に登録できるかどうかは DBMS の仕様と設定に依存します。

varyingInsert(entity, option)

共通カラムは自動設定

対応テーブルが共通カラムの自動設定対象になっている場合は、実行時に設定された通りに共通カラムの自動設定が行われます。 ゆえに、その場合は、プログラム上で共通カラムの値の設定をする必要はありません(設定しても自動設定処理にて上書きされます)。 自動設定された値は、登録処理後に Entity に格納されています。

もし、共通カラムの自動設定を無視した登録を行いたい場合は、Entity の disableCommonColumnAutoSetup() を登録前に呼び出すと、共通カラムの自動設定がされなくなります。 主に、システム移行のプログラム(移行プログラム)などで、共通カラムの値を保持したままデータを登録したいような場合に有効です。

排他制御カラムの自動設定

排他制御カラムは自動設定されるため、明示的に値を設定する必要はありません(設定しても自動設定処理にて上書きされます)。 自動設定された値は、登録処理後に Entity に格納されています。

カスケードはしません

例えば、会員 Entity が購入 Entity のリストを保持していたとしても、登録するのは会員、つまり、基点テーブルだけです。 自動で購入のリストも一緒に登録しにいくことはありません。これは DBFlute のポリシーですが、明示的に登録処理を指定していないものがディベロッパーの気付かないところで更新される、というような状態を避けるためです。 できた方が便利と思う場面も確かにありますが、別の機能でも同様ですが 明示的に が重視されています。

insert文に列挙されるカラム

Setterが呼ばれたカラムが登録される @since 1.0.5A

(newされた) Entity の Setter が呼ばれたカラムが、insert 文の項目に列挙されます(@since 1.0.5A)。 これを ModifedOnly と呼び、update() の方と同じ方式です。

ゆえに、呼び出していないカラムでDB上ので設定でデフォルト制約が存在する場合は、そのデフォルト値が登録されます。 ただし、登録処理後の Entity にそのデフォルト値が格納されることはありません。

※自動採番のPKや共通カラムや排他制御カラムは、Setterが呼ばれなくても特別な処理で列挙されます。

copy insertなら全カラム列挙 @since 1.0.5A

一方で、検索された(別のレコードの)Entityに対して値をセットして insert() する場合に限り、全カラム列挙になります。copy insertのようなケースが考えられ、Setter呼び出しがほとんど存在しない可能性があります。 デフォルト制約は利用できなくなりますが、既に別のレコードの値が土台として入っているため、その必要性はあまりないでしょう。

デフォルト制約付きNotNullカラム追加してもOK

DB変更で、デフォルト制約付きNotNullカラム追加された場合でも、修正すること無く対応できます。 新しいカラムはSetterが呼ばれないので、insert文に列挙されずにデフォルト制約が利きます。 また、copy insertのときは、そもそも既に格納されている別のレコードの値が登録されます。

1.0.5Aより前のバージョンでは

Entity に設定された null でない値のみ、insert 文の項目に列挙されます。 ゆえに、値が存在しない(nullの値の)カラムは、DB上ので設定でデフォルト制約が存在する場合はそのデフォルト値が登録されます。 ただし、登録処理後の Entity にそのデフォルト値が格納されることはありません。

※update()の方と方式が違うため、ちょっとわかりづらい仕様でありました。

更新系、列挙されるカラムのまとめ

バッチ更新やクエリ更新も含めた場合の、列挙されるカラムをまとめています(@since 1.0.5A)

基本的には ModifiedOnly であり、検索されたEntityへのセットの insert 系だけが挙動が変わる、と認識しておくと良いでしょう。

newしたEntityにセット ※通常はこちら

insert()
ModifiedOnly
batchInsert()
ModifiedOnlyで、複数のEntityでの最小公倍数のカラム
update()
ModifiedOnly
batchUpdate()
ModifiedOnlyで、複数のEntityにて呼び出しセットが一致の必要あり
queryUpdate()
ModifiedOnly

検索されたEntityにセット

insert()
全カラム列挙 ※copy insertを想定
batchInsert()
全カラム列挙 ※copy insertを想定
update()
※特に変わらず
batchUpdate()
※特に変わらず
queryUpdate()
※特に変わらず

バッチ更新は呼び出しセット一致

バッチ更新は、複数のEntityで呼び出しセットがバラバラの状態が許されません。 これは、不意のnullによる更新事故を防ぐためです。nullで更新するなら、明示的にnullをセットする方が良いでしょう。 また、バッチ更新には、第二引数で更新カラムをSetter呼び出しとは無関係に明示するオプションもあり、自由度が求められる場合はそちらを使うと良いでしょう。

ただ、そもそもバッチ更新は、あまり利用頻度は少ないものです。固定値を複数レコードに更新するのであれば queryUpdate() が使えるからです。複数レコードでそれぞれ違う値で更新する、とか、複数レコード更新でも排他制御をしたい、という場合のみ、バッチ更新の出番です。

一方で、バッチ登録は、もともとレコード自体が存在していませんので、セットしてなければ単にnullで登録されるという仕様で問題ないだろうと考えました。 また、実際の現場でそのように実装している箇所が多く見られたからです。