概要
autoincrement機能を持たないOracleをSkinny ORMで扱うときに、IDの自動採番をどうやって行うか。
前提
- Oracleへの接続はできてる
- 以下のSQLで生成されるテーブルとシーケンスがある
CREATE TABLE HOGE (
ID NUMBER(10) NOT NULL,
NAME VARCHAR2(40) NOT NULL,
PRIMARY KEY (ID)
);
CREATE SEQUENCE HOGE_SEQ
INCREMENT BY 1
START WITH 1
NOMAXVALUE
NOMINVALUE
NOCYCLE
NOCACHE;
方法
とりあえず2つやってみた
Oracleに全部任せる
- triggerを利用して、insert時にnextvalを取得して採番する
という方針。
まずtriggerを作る
create or replace trigger hoge_id_trg
before insert on hoge for each row
begin
select
hoge_seq.NEXTVAL
into :new.id
from dual;
end;
modelの実装はこんな感じ。override def useAutoIncrementPrimaryKey = false
しておくことが必要。
Hoge.scala
package model
import skinny._
import scalikejdbc._, SQLInterpolation._
case class Hoge(id: Long, name: String)
object Hoge extends SkinnyCRUDMapper[Hoge] {
override lazy val defaultAlias = createAlias("hoge")
// autoincrement を切る
override def useAutoIncrementPrimaryKey = false
override def extract(rs: WrappedResultSet, n: ResultName[Hoge]) = new Hoge(
id = rs.long(n.id),
name = rs.string(n.name)
)
val h = Hoge.defaultAlias
def create(name: String): Long = DB localTx {
implicit s =>
// ID列はOracleでよしなにしてくれる
Hoge.createWithNamedValues(h.name -> name)
}
}
Skinny ORMに任せる
autoinclementの処理時に、独自に自動採番ルールを定義できる
-
useExternalIdGenerator
をoverrideしてtrueに -
generateId
を実装
Hoge.scala
package model
import skinny._
import scalikejdbc._, SQLInterpolation._
case class Hoge(id: Long, name: String)
object Hoge extends SkinnyCRUDMapper[Hoge] {
override lazy val defaultAlias = createAlias("hoge")
// useAutoIncrementPrimaryKeyはtrueのまま
// useExternalIdGeneratorをoverrideする
override lazy val useExternalIdGenerator = true
// generateIdを実装する
override def generateId: Long = DB localTx {
implicit session =>
// ナマのSQLを走らせて、NEXTVALの結果を得る
sql"select hoge_seq.NEXTVAL as id from dual".map(_.long("id")).first().apply.get
}
override def extract(rs: WrappedResultSet, n: ResultName[Hoge]) = new Hoge(
id = rs.long(n.id),
name = rs.string(n.name)
)
val h = Hoge.defaultAlias
def create(name: String): Long = DB localTx {
implicit s =>
Hoge.createWithNamedValues(h.name -> name)
}
}
まとめ
とりあえずどちらの方法でも、IDを自動採番してinsertすることには成功した。
なんかもうちょっとうまい方法があるような気はしてますが。
Oracle+Skinny ORMの調査中にハマったポイントだったのでメモとして残しておきます。
誰かの参考になれば幸い。