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 しおしお
おわり。