🤝

JavaのRecord型とMyBatisマッピングの親和性について、思い知らされた話。

2024/07/13に公開

最近JavaでWEBアプリ開発をしているのですが、MyBatisのマッピングで若干時間を取られてしまったので、記事に残しておきます。

公式ドキュメント読みつつマッピングの仕組みを理解していれば、こんなことにはならなかったはず。いつものように反省。

事の発端

途中からデータの持ち方をrecordからclassに変更したら、データが取れなくなった・・・

原因

キャメルケース/スネークケースの命名規則の自動認識について、理解が甘かった。

結論

record:設定ファイルに追加の構成は不要
class:設定ファイルでmapUnderscoreToCamelCase=trueにする必要がある

具体的にどういうことが起こったか

最初、recordでデータ受け取ろうと思ってた

UserEntity.java
package com.example.mapping_demo.entity;
import java.time.LocalDateTime;

public record UserEntity(
        int userId,
        String userName,
        LocalDateTime createdAt,
        LocalDateTime updatedAt) {
}

データ受け取れた!よし。

~その後~

今後のこと考えたら、やっぱclassにしといた方がいいかもしれんな

UserEntity.java
package com.example.mapping_demo.entity;
import lombok.Data;
import java.time.LocalDateTime;

@Data
public class UserEntity {
    private int userId;
    private String userName;
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;
}

あれ、中身がない・・・でも要素としては存在することはわかってる。

なんでマッピングできてないんだろう、recordの時は取れてたんだけどな。

解決法

設定を追記するだけ(なんかすみません)。

application.properties
mybatis.configuration.map-underscore-to-camel-case=true

ちゃんと調べてみた

MyBatisでJavaのrecordを使用する場合、recordのコンストラクター引数名をSQL結果セット内の列名と照合して、キャメルケース/スネークケースの命名規則の自動認識をしてくれているらしい。
(MyBatis v3.5.10以降の機能で、コンストラクター自動マッピング機能の一部)

というわけで、recordの場合は標準Javaクラスで通常必要となる明示的なマッピング構成が不要とのこと。至れり尽くせりです。

書いてみて思ったこと

設定系は見落としがちなので、早めに確認する意識を持たないとですね。
そして、便利な機能が増えてくれる = 何でもやってくれる = 割と勝手に動いてくれる
これがある意味恐ろしいですね。できる気分にさせてくれちゃうのが厄介ですが、根本的な仕組みや仕様の理解を怠らず、これからも楽しく開発していこうと思います。

Discussion