DomaでOracle12CのIdentity Columnを使う方法です。
DomaのOracleDialectなどなどでは、使うことが出来ないので色々いじってあげる必要があります。
Oracle12C用のDialectを作る
基本は、OracleDialectと同じでいいので継承して作ります。
変更点は、Identity Columnを使えるようにするためにsupportsIdentityでtrueを返します。
また、Statement.getGeneratedKeys()でデータベース側で採番した値を取得したいので、supportsAutoGeneratedKeysでもtrueを返します。
object Oracle12Dialect : OracleDialect() { override fun supportsIdentity() = true override fun supportsAutoGeneratedKeys() = true }
Configクラスを作る
getDialectでは、先程作ったOracle12C用のDialect実装を返します。
getCommandImplementorsは、insert時のprepareStatementでprepareStatement(String sql, int[] columnIndexes)を使用するように変更します。
Domaの実装だとIdentity Columnの採番された値ではなく、ROWIDの値がStatement.getGeneratedKeys()で返されてしまうので変更しています。
あとは、接続先の設定などなどをしてあげます。
object AppConfig : Config { private val dialect: Dialect = Oracle12Dialect override fun getCommandImplementors(): CommandImplementors { return object : CommandImplementors { override fun createInsertCommand(method: Method, query: InsertQuery): InsertCommand { return object : InsertCommand(query) { override fun prepareStatement(connection: Connection): PreparedStatement { return if (query.isAutoGeneratedKeysSupported) { connection.prepareStatement(sql.rawSql, intArrayOf(1)) } else { super.prepareStatement(connection) } } } } } } private val dataSource by lazy { val oracleDataSource = OracleDataSource() oracleDataSource.user = "siosio" oracleDataSource.setPassword("siosio") oracleDataSource.url = "...." LocalTransactionDataSource(oracleDataSource) } override fun getTransactionManager(): TransactionManager { return LocalTransactionManager(dataSource.getLocalTransaction(jdbcLogger)) } override fun getDataSource(): DataSource = dataSource override fun getDialect(): Dialect = dialect }
Entityを作る
主キーのGeneratedValueをGenerationType.IDENTITYなカラムにしてあげます。
@Entity(immutable = true) @Table(name = "users") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) public final Long id; public final String name; public User(final Long id, final String name) { this.id = id; this.name = name; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + '}'; } }
Daoを作る
@Dao(config = AppConfig.class) public interface UserDao { @Insert Result<User> insert(User user); }
テーブルを作る
idカラムをidentityなカラムにしてあげます。
create table users( id number(15) generated always as identity , name varchar2(150 char), primary key (id) )
検証用のmainを作る
DaoのImplをルックアップしてきて、insertを呼び出している感じです。
fun main(args: Array<String>) { AppConfig.transactionManager.required { val user = User(null, "しおしお") val result = dao<UserDao>().insert(user) println("result.entity = ${result.entity}") } }
実行!!
登録した結果、Entityの内容がUser{id=9, name='しおしお'}となっているのでいい感じに動きました。
4 18, 2017 8:47:12 午前 org.seasar.doma.jdbc.tx.LocalTransaction begin 情報: [DOMA2063] ローカルトランザクション[142666848]を開始しました。 4 18, 2017 8:47:12 午前 dao.UserDaoImpl insert 情報: [DOMA2220] ENTER : クラス=[dao.UserDaoImpl], メソッド=[insert] 4 18, 2017 8:47:13 午前 dao.UserDaoImpl insert 情報: [DOMA2076] SQLログ : SQLファイル=[null], insert into users (name) values ('しおしお') 4 18, 2017 8:47:13 午前 dao.UserDaoImpl insert 情報: [DOMA2221] EXIT : クラス=[dao.UserDaoImpl], メソッド=[insert] 4 18, 2017 8:47:13 午前 org.seasar.doma.jdbc.tx.LocalTransaction commit 情報: [DOMA2067] ローカルトランザクション[142666848]をコミットしました。 result.entity = User{id=9, name='しおしお'} 4 18, 2017 8:47:13 午前 org.seasar.doma.jdbc.tx.LocalTransaction commit 情報: [DOMA2064] ローカルトランザクション[142666848]を終了しました。
テーブルをのぞいてみるとちゃんと登録されてます。
08:48:29 SQL> select * from users where id = 9; ID NAME ---------- ------------------------------ 9 しおしお
おわり。