LoginSignup
7
7

More than 5 years have passed since last update.

Skinny ORMとOracleのSequenceでIDの自動採番をする

Posted at

概要

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の調査中にハマったポイントだったのでメモとして残しておきます。
誰かの参考になれば幸い。

7
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
7