Doma2 with Kotlin

Post on 13-Apr-2017

467 views 1 download

Transcript of Doma2 with Kotlin

Doma2 with Kotlin

【7/9(土)】Doma勉強会 in 東京

@yy_yank

          こいつです

          ・viとサクラエディタ好き

          ・小物SIer          ・JavaとKotlinが好き

ヤンク(@yy_yank)

自己紹介

とつぜんですがワタクシ、

Doma2のコントリビューターなんです

fix typo(ドヤッ)

はい、すいませんでした

with

with

with

with

Doma2、Kotlinでも使えるよ!!!の話

(一応・・・) Doma とは

・めっちゃ良いORM・Domain Oriented Database MApping Framework・Annotation Processingでのコンパイルチェック素敵

・JRE 8以上でうごく

・2Way-SQL

※NASAではない

(一応・・・) Kotlinとは

・JVM言語

・JetBrains製・Gradleスクリプトも書ける(ようになる)・Spring Initializrでも選択可能

・Null Safety(らしい)

・ScalaとGroovyのいいとこどり(らしい)

※ボクは昔のロゴの方が好き

アジェンダ

Doma2 ・Entity ・Embeddable ・Domain ・DaoKotlin ・kapt ・java.util.stream.Stream

アジェンダ

Doma2 ・Entity ・Embeddable ・Domain ・DaoKotlin ・kapt ・java.util.stream.Stream

Entity@Entity(immutable = true)data class Person( @Id @GeneratedValue(strategy = GenerationType.IDENTITY) val id: Int? = null, val name: Name, val age: Int?, val address: Address, @Version val version: Int = -1)

アジェンダ

Doma2 ・Entity ・Embeddable ・Domain ・DaoKotlin ・kapt ・java.util.stream.Stream

Embeddable

package sample

import org.seasar.doma.Embeddable

@Embeddabledata class Address(val city: String, val street: String)

アジェンダ

Doma2 ・Entity ・Embeddable ・Domain ・DaoKotlin ・kapt ・java.util.stream.Stream

package sample

import org.seasar.doma.Domain

@Domain(valueType = String::class)data class Name(val value: String)

Domain

アジェンダ

Doma2 ・Entity ・Embeddable ・Domain ・DaoKotlin ・kapt ・java.util.stream.Stream

Daopackage sample

import org.seasar.doma.*import org.seasar.doma.jdbc.Result

@Dao(config = AppConfig::class)interface PersonDao { @Script fun create() @Script fun drop() @Select fun selectById(@ParameterName("id") id:Int): Person @Insert fun insert(person: Person): Result<Person> @Update fun update(person: Person): Result<Person> @Delete fun delete(person: Person): Result<Person>}

@Dao(config = AppConfig::class)interface PersonDao {

@Script fun create() @Script fun drop()

Dao

@Select fun selectById(@ParameterName("id") id:Int): Person

@Insert fun insert(person: Person): Result<Person>

Dao

@Update fun update(person: Person): Result<Person> @Delete fun delete(person: Person): Result<Person>

Dao

特に言うことなし

(別にKotlinじゃなくても)コードがシンプルでキレイ

あえていうならgettter/setterが消えてLombokぐらいの活躍はしている!

コードは全て

https://github.com/domaframework/kotlin-sample

から拝借しました!

DomaのKotlinサポートのページに詳しく指針が出ているので迷うことなし!

http://doma.readthedocs.io/ja/stable/kotlin-support/

Kotlinサポート

ざっくり言うと

・data class使おう

・イミュータブルなクラスにしよう

・コンストラクタは1つだけにしよう

・kaptにハマったら@DaoはJavaにするなど

混在させるのもアリ

アジェンダ

Doma2 ・Entity ・Embeddable ・Domain ・DaoKotlin ・kapt ・java.util.stream.Stream

・kaptはJSR269をKotlinでも使えるようにしてくれる

コンパイルツール(個人的にはaptってやめて欲しい名前)・Doma 2のAnnotation Processingに対応している

・以前のツラミ->backpaper0さんの資料

http://backpaper0.github.io/ghosts/kotlin-doma.html・Kotlinの最新version 1.0.3で改善されたりしてる

・Doma 2としてもサポートしてくれていて

ツラミ減

kapt

kaptのツラミ(backpaper0さん資料抜粋)

・少なくとも1つ注釈処理のつくJavaクラスが必要問題

→解消されたっぽい!

・arg0、arg1問題

→@ParameterNameで解消

多分これのおかげです(よね?)

kaptのツラミ

GitHubのissueにもあったのでこれで間違いなさそう

・issuehttps://github.com/domaframework/doma/issues/129

・javadochttp://doma.seasar.org/apidocs/org/seasar/doma/ParameterName.html

kaptのツラミ

@Select fun selectById(@ParameterName("id") id:Int): Person

kaptのツラミ

@ParameterNameによりarg1、arg2...問題が解消された

アジェンダ

Doma2 ・Entity ・Embeddable ・Domain ・DaoKotlin ・kapt ・java.util.stream.Stream

・KotlinはJDK6対応

・JDK8対応はまだらしい

・でもボクはJavaでいう

@SelectR select(Integer id, Function<Stream<T>, R> mapper)したい!!!!

java.util.stream.Stream

・KotlinはJDK6対応

・JDK8対応はまだらしい

・でもボクはJavaでいう

@SelectR select(Integer id, Function<Stream<T>, R> mapper)したい!!!!

ということで検証

java.util.stream.Stream

 結論:出来た(なんでか分かんないけど普通に動くっぽい)

 結論:出来た(でもKotlinからStream API使いにくい)

@Select(strategy = SelectType.STREAM) fun selectById( @ParameterName("id") id:Int, func :java.util.function.Function<java.util.stream.Stream<Person>, Name>): Name

Dao

@Test fun test2() { tm.required { val personName = dao.selectById(1, Function { it.map {it.name}.findFirst().orElseThrow { Exception("あってほしい!") } }) Assert.assertEquals(Name("SMITH"), personName) }}

Test Code

@Test fun test2() { tm.required { val personName = dao.selectById(1, Function { it.map {it.name}.findFirst().orElseThrow { Exception("あってほしい!") } }) Assert.assertEquals(Name("SMITH"), personName) }}

Test CodeSAM(Single Abstract Method)

@Test fun test2() { tm.required { val personName = dao.selectById(1, Function { it.map {it.name}.findFirst().orElseThrow { Exception("あってほしい!") } }) Assert.assertEquals(Name("SMITH"), personName) }}

Test CodeFunction#applyをFunction{}とかける

@Test fun test2() { tm.required { val personName = dao.selectById(1, Function { it.map {it.name}.findFirst().orElseThrow { Exception("あってほしい!") } }) Assert.assertEquals(Name("SMITH"), personName) }}

Test Codeit = Stream<Person>stream -> streamと思ってくれれば。

@Test fun test2() { tm.required { val personName = dao.selectById(1, Function { it.map {it.name}.findFirst().orElseThrow { Exception("あってほしい!") } }) Assert.assertEquals(Name("SMITH"), personName) }}

Test Code Javaで書くならstream -> stream.map(person -> person.getName()).findFirst().orElseThrow(()-> throw new Exception(“あってほしい! ”)

うん。。

でもどうせならKotlin的には。。

@Select(strategy = SelectType.STREAM) fun selectById( @ParameterName("id") id:Int, func : (person : Person) -> Name): Name

Dao

@Select(strategy = SelectType.STREAM) fun selectById( @ParameterName("id") id:Int, func : (person : Person) -> Name): Name

Dao

ここをこうして

@Test fun test2() { tm.required { val personName = dao.selectById(1, {it.name}) Assert.assertEquals(Name("SMITH"), personName) }}

Test Code

@Test fun test2() { tm.required { val personName = dao.selectById(1, {it.name}) Assert.assertEquals(Name("SMITH"), personName) }}

Test Codeこうじゃ

エラー: [DOMA4247] @Selectのstrategy要素に

SelectStrategyType.STREAMを設定した場合、

Function型のパラメータが必要です。 at sample.PersonDao.selectByIdエラー1個

Domaさん賢い!!!!

#そこじゃない

・Doma2はKotlinでも普通に使える

・手軽な感じでコード書くには良いのかも

・KotlinからStream APIは使いにくい

(あんまりDoma2関係ない)・でもJavaで使ってもDoma2は充分気持ち良い

・お世辞じゃなくDoma2は素敵

・対応の早さ、柔軟さも素敵

まとめ

Domaは素敵!!!!