Believe you can

If you can dream it, you can do it.

サーバサイドKotlinでKomapperを使ってみよう

Kotlin製ORマッパーのKomapperが5月に1.0のリリースされると聞いてSpringBoot上で試してみました。といってもサンプルソースも豊富なのでそれに毛が生えた程度です。。

CRUD

H2を利用してpersonテーブルを用意してCRUDを動かします。

create table person
(
    id    int GENERATED ALWAYS AS IDENTITY (START WITH 3) PRIMARY KEY,
    name  varchar(255) not null,
    email varchar(255) not null
);

エンティティ、マッピング定義

テーブルと対になるエンティティとPKなどの項目にアノテーションを定義して項目マッピングを行います。

data class Person(
    val id: Int? = null,
    val name: String,
    val email: String,
)

@KomapperEntityDef(Person::class)
data class PersonDef(
    @KomapperId
    @KomapperAutoIncrement
    val id: Nothing,
)

クエリ実行

QueryDSLを利用してSQLを実行します。メソッドチェーンでやりたいことをつなげていく感じなので直感的でわかりやすいですね。

@Service
class PersonService(
    private val database: JdbcDatabase
    ) {
    fun findAll(): List<Person> {
        return database.runQuery {
            val p = Meta.person
            QueryDsl.from(p).orderBy(p.id)
        }
    }

    fun findById(id: Int): Person {
        return database.runQuery {
            val p = Meta.person
            QueryDsl.from(p).where{ p.id eq id }.first()
        }
    }

    @Transactional
    fun insert(name: String, email: String): Person {
        return database.runQuery {
            val person = Person(name = name, email = email)
            val p = Meta.person
            QueryDsl.insert(p).single(person)
        }
    }

    @Transactional
    fun update(id: Int, name: String, email: String): Person {
        return database.runQuery {
            val person = findById(id)
            val p = Meta.person
            QueryDsl.update(p).single(person.copy(name = name, email = email))
        }
    }

    @Transactional
    fun delete(id: Int) {
        database.runQuery {
            val person = findById(id)
            val p = Meta.person
            QueryDsl.delete(p).single(person)
        }
    }
}

結合

テーブル結合をしたSQLも試してみます。チームテーブル、チームメンバーテーブルを用意して、personテーブルを含めた3テーブルの結合を行います。
DDLは次の通りです。

create table team
(
    id   int GENERATED ALWAYS AS IDENTITY (START WITH 3) PRIMARY KEY,
    name varchar(255) not null
);

create table team_member
(
    id        int GENERATED ALWAYS AS IDENTITY (START WITH 4) PRIMARY KEY,
    team_id  int not null,
    member_id int not null
);

エンティティとマッピング

data class Team(
    val id: Int? = null,
    val name: String,
)

@KomapperEntityDef(Team::class)
data class TeamDef(
    @KomapperId
    @KomapperAutoIncrement
    val id: Nothing,
)

data class TeamMember(
    val id: Int? = null,
    val teamId: Int,
    val memberId: Int,
)

@KomapperEntityDef(TeamMember::class)
data class TeamMemberDef(
    @KomapperId
    @KomapperAutoIncrement
    val id: Nothing,
)

left joinを行います。leftJoinメソッドで結合するテーブルを指定し、selectメソッドで取得するカラムを指定します。

@Service
class TeamService(
    private val database: JdbcDatabase
) {
    fun findById(id: Int): TeamDTO? {
        val g = Meta.team
        val m = Meta.teamMember
        val p = Meta.person
        val result = database.runQuery {
            QueryDsl.from(g)
                .leftJoin(m) { g.id eq m.teamId }
                .leftJoin(p) { m.memberId eq p.id }
                .where { g.id eq id }
                .orderBy(m.id)
                .select(g.id, g.name, p.id, p.name, p.email)
        }

        val members = result.map {
            Member(it[p.id]!!, it[p.name]!!, it[p.email]!!)
        }
        val member = result.first()
        val id = member[g.id]
        val name = member[g.name]

        return TeamDTO(id!!, name!!, members)
    }
}

完成したソースは↓です。

github.com

感想

SQLをメソッドチェーンで組み立てていくことができるので悩まずに実装できるのがいいですね。アノテーションプロセッサーを利用しているのでMetaで指定できるテーブルはコンパイルをしていないと怒られてしまうのは注意が必要です。(大した問題ではないが)

R2DBCに対応しているORマッパーは少ないので採用候補に上がるプロジェクトも多いんじゃないでしょうか。
基本機能を試した程度ですが、これから採用実績は増えていくこと間違いなしだと思います!!

3/16(水) 日報

3月末までは充電期間のためお休みをいただいております。
就業までの間にお休みをいただく(有給消化的な)のは初めてで、ダラけた生活を送ってしまっているので日報を書くことでダラけない生活を送る努力をしてみようと思い、今日から日報を書いていこうと思います。

興味ないと思いますが、お付き合いいただければです <( )>

起床

  • サプリを摂りつつ、コーヒーを落とす
  • マンガアプリを読む
  • コーヒーを飲みつつ洗濯物を干す
  • ボケーとする

運動

  • 腹筋ローラー:20回を3セット
  • フィットネスバイク:30分
  • オイコスで朝食

昼食

  • 早めの昼食
  • 洗い物など

お出かけ

  • 妻を送迎
  • 娘とダラダラお出かけ
    • ペットショップはしご
    • アポ無しで実家に行く
    • 善光寺のすみっコぐらし堂でお買い物

  • 図書館でブラブラ
  • 妻のお迎え

帰宅〜夕食

  • 洗濯物取り入れ
  • 息子のお迎え
  • ボケーとする
  • 夕食

寝るまで

  • ブログ書く
  • 洗い物など
  • YouTubeライブの勉強会参加
  • Spring Boot+Kotlin+Komapperのサンプル実装
  • 風呂

明日やりたいこと

  • [重要]本の執筆
  • 読書
  • バリカン(坊主)
  • バイク自賠責加入とバッテリー用意
  • 服買いに行きたい

退職しました

退職エントリが盛り上がっていましたが、自分も退職エントリです。
2/25を最終出社日、3/31をもって2年11ヶ月勤めた会社を退社することになりました。現在は有給消化というか特別休暇扱いで充電期間です。

なんで転職?

Twitter上でカジュアル面談受けているとか言っていたので、察していた方もいたかと思いますが、会社も僕自身としても不本意な結果となってしまったかなと思っています(そうであってほしいな)。
詳しい理由をこの場で語らないので、読んでくださってる方からすればもどかしい感じになってしまいますが、気になる・知りたいという方はご飯でも誘ってください。

会社や開発部・プロダクトが嫌になったとか、現職との人間関係がよくないといった理由ではないことは明言しておきます。個人的にはR&D部門に異動になりこれからといった気持ちでしたし、上司・同僚、他部門の皆様も素晴らしいメンバーでいい環境で働けていたと思っています。

現職への感謝

所属していた約3年間はとても楽しく刺激的で濃厚な経験させていただきました。
挑戦を許してくれる組織の中でときにはわがままを聞いていただき、たくさんの挑戦とサポートをしてくれたCTOやEM、同僚には感謝しかありません。またその結果、負債となるものも残してしまい申し訳なく思っております。。

転職活動

過去の転職はリファラルやTwitterナンパで比較的苦労せずに転職をしてきました。今回は転職サイト経由でカジュアル面談を受け、面談→応募→面接という正規の流れを行う転職活動でした。次の就業先を急いで探す必要があったものの、エージェントへの登録はなんとなくという理由で行いませんでした。

利用した転職サイトは経歴書のインポートができたFindlyとLAPRASがメインでWantedlyやForkwellを後から増やした感じで声がけを待ちつつ、こちらからもアプローチしていった感じで動きました。
声をかけていただいた企業でプロダクトや開発体制に興味を感じたらカジュアル面談をさせていただく形をとっていました。お時間をいただいた企業様には感謝しており、また僕のことを評価していただき応募してほしいと言っていただいたことはとても嬉しいお声で救われました。

ただ、今回の転職は急なこともあり家族にもだいぶ心配をかけてしまったため、家族の声を優先した結果、スタートアップフィルターをかけざるを得ませんでした。そのフィルターが発動したために応募しないという決断を行ったこともあり、親身になってくれた企業様や担当者様には大変申し訳なく思っております。

今後は?

4月からはECサイトを運営する企業でJavaエンジニアとしてフルリモートで働く予定です。
応募した理由はカルチャーフィットを感じたのと、担当予定業務に関わることでサービス・ビジネスの成長を感じたいと考えたためです。
入社まで残り数週間、色々な不安と期待を感じつつテックブログを読み込んだりmeetup動画を見て勉強とモチベーションアップをしていこうと思います。

最後に退職エントリには欲しいものリストもセットと聞いたので作ってみました(これでいいのかな?)。

www.amazon.jp

ダイエット成功!7ヶ月で27kg痩せた

2週に1回は投稿したいと年始の目標を立てたものの、早速守れていない僕です。。
(技術的なネタも減りつつあり。。。)
言い訳させてもらえると年明けそうそうヘビーな状況に陥ってしまい、現在進行形で落ち着いていないからです。来週前半には落ち着いてご報告できることもあるかと思うのでその時が来たらブログかTwitterで報告させてください。

タイトルの通り、2021年6月からダイエットを初めて本日時点(3/3)で27kgのダイエットに成功しました。
どんなことをして痩せたのか、これからダイエットを始める方の参考になれば幸いです(人によって合う・合わないがあると思うので自己責任でお願いします)

食事制限

ダイエットを始める時の体重が3桁あったのと、全く動いていない体でいきなり運動したりして、膝や腰を痛め危険があったので、食事制限から始めました。
まずは炭水化物を減らす目的で、朝食のごはんをオートミールに変更、夜ごはんはおかずのみでごはんは食べないという食生活に変更しました。

主食の摂取を減らせば腹持ちも悪く、すぐにお腹が空いてしまうのですが、その時はゆで卵やプロテインでお腹を満たしつつタンパク質を取るようにしています。あとは、栄養バランスが崩れて体調を崩さないように、マルチビタミンを摂取するなどしました。オートミールはマジでうまくて自分にとってはむしろご褒美感覚でした。

レコーディング

食事制限ができているのかは正直わからんので、同僚から進められた「あすけん」でカロリー計算も行いました。
厳密な計算は難しいのでざっくりと食べたものを記録する感じです。これのおかげで「まだ食べれる」「夜ごはんはセーブしなきゃ」など調整がしやすかったので、記録を取るのマジ大事。

有酸素運動

食事制限だと停滞期でなかなか体重が落ちない状態がやってきて、心が折れそうになります。
そこで新たに増やしたのが、フィットネスバイクによる有酸素運動です。某転職サイトのキャンペーンで5万円をいただいたタイミングでもあったので、フィットネスバイクを購入しアニメやYouTubeを見ながら30〜60分ほど漕いでいました。
ここ数年、運動で汗をかくことがなかったので気持ちよく続けることができ、現時点の総距離が4300kmを超えています。めっちゃ漕ぎましたね。。。

まとめ

もともとの体重が多かったので始めれば痩せやすいってのもあったかと思いますが、自分でも頑張ったなーと思います。
ただ、筋トレを行わなかったためか、めちゃくちゃ冷え性になってしまいました。。きっと筋肉が落ちたものと。。。
これからのダイエットは筋トレも計画しつつ行っていこうと思います。

結婚前の体重まで戻せればと思いつつ、あと数キロ痩せたらリバウンドしないことを目指そうと思います。

XubuntuでCtrlとCapsLockを入れ替えるメモ

デスクトップPCをWindowsからXubuntuに切り替えて1週間。
日本語切り替えをCtrl+Spaceで切り替えていますが、キー自体はmacと同じ切り替えなので問題ないんですが、普段macではHHKBを使っています。
Ctrlの位置がCapsLockと逆なので日本語切り替えが違っていて不便でした。デスクトップPCでもHHKBを使えばいいんですが、BluetoothのHHKBなためレシーバーがないデスクトップでは利用できないのです。。
ということで、忘れないように切り替え方法をメモしておこうと思います。

調べたところ gnome-tweaks を使うとかんたんに切り替えることができるようです。
次のコマンドでインストールと起動を行います。

$ sudo apt install gnome-tweaks
$ gnome-tweaks

起動したら キーボードとマウス を選び 追加のレイアウトオプション をクリック。
Caps Locl behabiorCaps Lock is also a Ctrl を選択し、 Ctrl positionCtrl と Caps Lock を入れ替える を選択したら再起動。
これで設定は終わり。これでいつもの切り替え方法と同じになったぜ!

積読本消化のためにはじめたこと

読まずに溜まっていく技術書たちがあるのについまた購入してしまうことってありますよね...?
エンジニアの方なら経験があると思いますが、僕もその一人です。。
積読本を消化すること」を今年の目標の一つに上げていますが、年末から行っている工夫を紹介したいと思います。

まず次を用意します。

  • 読みたい本
  • 小さめの付箋紙

そして本を読んでいきます。読み始めるのに苦労しているって人はなんとか読み始めてください。そこには工夫はありませんので頑張ってください(根性論)。。
10分から20分ぐらいを目標に読み進めていきます。普段本を読み慣れていない人は短い時間を繰り返すことを目指したほうがいいです。自分がそうでした。

通常であればしおりを入れておしまいとなるのですが、しおりの代わりに付箋に今日の日付を書いてしおり代わりに貼っておきます。
これを毎日続けてください。そうすると1日で読める量が分かり、ちょっとしたバーダウンチャートのように進捗が分かります。

そうです!進捗の見える化ですね。
進捗がわかるとゴールが分かり、モチベーションにも繋がります。

自分はこの方法で、年末から5冊の技術書を読むことができました。
単純な僕はこの工夫で読み進めることができていますので効果があるかもです。同じ悩みを持っている方は試してみてください。
ではでは~ f:id:chichi1091:20220115232301j:plain

謹賀新年

明けましておめでとうございます!今年もよろしくお願いします!!
厄年を開けたのに新年早々、水漏れやウォーターサーバの故障が起きてしまい、お祓いに行こうが悩んでいます。。

積読本の消化

歳とか老いを言い訳にしたくないけど本を読むことが出来ていないのでチョットずつでも読んでいきたい。年末からちょっとした工夫を初めて何冊か読み進めることができているのでそのうち紹介したい。

フロントエンド

年末は仕事でNuxt.jsを触れる機会が多かったが、スキル・知識不足を痛感することがあったので、メンバーに迷惑をかけない程度までスキルアップを目指すのと、Nuxt.js以外のフロント技術もキャッチアップしたい。

バックエンド

仕事ではREST fulばかりでGraphQLやgRPCなどのキャッチアップが疎かになってしまっているので何か作ってみたい。あとは関数型言語に挑戦したいかな。

その他

  • アウトプット、インプットを増やす ブログもできれば2週に1つは投稿できるようにして、勉強会も積極的に参加していきたい。よいインプットができればきっとよいアウトプットもできるはず。
    夏に行われる技術書典にも頒布できるように頑張りたい。

  • 犬を飼う 娘が欲しいと言い出したことがきっかけで調べていたらものすごく飼いたくなってる...
    生き物を飼うのはかんたんではないので家族と相談した上でですかね。

何やらやりたいことをたくさん書いてしまいましたが、やり遂げられるように気負わないでゆるーく進めていければですかね。