flavorじっくりコトコト煮込んだみかん2。知らないことを知りたい。この広告は、90日以上更新していないブログに表示しています。postgresKotlinでWebアプリケーションを作るにあたり、SQLを直接記述できるタイプのO/Rマッパー(本稿ではSQLマッパーと呼びます)を探し求めました。SQLマッパーに求める機能SQLマッパーに求める機能はBindとMapです。この記事ではBindとMapを次のように定義します。BindSQLに埋め込んだプレースホルダー(名前付きが望ましい)に対応するパラメーター群を渡す機能。ようなSQLに、minPriceとmaxPriceプロパティを持つオブジェクトを渡す。Map実行結果として得られた行をオブジェクトにマッピングする機能。プロパティを持つオブジェクト(のリスト)として返す。次のような機能は(あれば嬉しいかもしれませんが)特に求めていません。動的にSQLを組み立てる機能*1snake_caseのカラムをcamelCaseのプロパティにMapする機能*2最初はなんとなくsql2oを使っていましたが、プロパティの型によっては思い通りにBind/Mapされないことがあり、各種のSQLマッパーがどのような型に対応しているのか真面目に検証してみようと思いました。検証対象とバージョン上記の求める機能を持つSQLマッパーとして、次の5つのライブラリを検証しました。1.6.0対象とするデータベースはPostgreSQLです。基本的な情報は次の通りです。最新については2019-09-29時点の情報です。する型のカラムを含むテーブルsql_mapper_testを作成し、そこにテストデータを1行INSERTしておきます。varchar(10)[]);BindとMapについて、それぞれ次のように対応可否を検証します。ようなSQLでテストデータと同じ値をBindして、1が返ってくれば対応していると判断。いうSQLで、テストデータと同じ値が返ってくれば対応していると判断。検証に使用したソースコードは次のリポジトリにあります。結果は次のスプレッドシートに記載しています。それぞれのセルは、1列目のカラムを2列目の型でBind/Mapした結果を表します。発生した例外の名前https://docs.google.com/spreadsheets/d/1Tf3uB5xFIZnP1ieSu9JQdKaGDY_XfJyGJYleAXI3328/edit?usp=sharing解説まず最初に、timetz⇔OffsetTime、url⇔URLの変換は試した全ライブラリでできませんでした。Templateは同じような結果となりました。基本的にはJDBCドライバー任せで、Bind時はJDBCドライバーが対応していればBindできます。Map時はJDBCドライバーが返す値をそのままキャストして返すので、期待している型とは異なる型が返ってくる場合があります。APIの型で受け取ることはできません。integer型のカラムをBigDecimalで受け取りたいと思っても、返ってくるのはIntegerです。ような記述が可能です。APIの型で受け取ることもできます。配列型であれば受け取れました。Integer[]をパラメーターとしてBindすることはできなかったので、注意が必要です。MyBatisの場合、(本稿の狙いとはズレますが)動的なSQL組み立て機能が強みなので、<foreach>を使えばINなどのパラメーターを展開できます。JDBIはPostgresプラグインを有効にするとほぼ全ての型をBind/Mapでき、一番良い結果となりました。他の全ライブラリが対応しているjava.sql.Dateとjava.sql.TimeをMapできないのは意外でしたが、LocalDateやLocalTimeを使えば問題ありません。ような記述が可能です。APIには対応していません。細かいですが、integerをBigDecimalで受け取る際は、一度doubleに変換されて、桁数がずれてしまいました。ような記述が可能です。大まかにまとめると次のようになります。比較したSQLマッパーのPostgreSQLの型への対応度合いは、次の順で良い結果となりました。DbUtilsJDBIは、ドキュメントに対応している型が明確に記述されていたのも好感が持てました。試しに使ってみようと思います。各種ライブラリの検証結果で対応していない型についても、Bind時にSQLの書き方を工夫したり、コンバーターを自作したりすれば対応できるので、ライブラリの評価はこれだけで決まるものではありません。対応している型を把握した上でライブラリを使うことが大切だと思うので、その助けになれば幸いです。この結果はJDBCドライバーの実装に大きく依存するので、他のDBやJDBCドライバーを使う場合は、この結果をそのまま使えないことに注意してください。注意を払いましたが、すべてのライブラリにおいてドキュメントやソースコードを完全に読んだわけではないので、検証方法がおかしいところなどありましたら、ぜひお知らせください。#jsug*1:とは言いながら、INのパラメーターを展開する機能はあると嬉しいので、追加で検証してます。*2:チームメンバーに聞いたら、気持ち悪いからasを書きたいという声が多数でした。いう記法を使うと動作しないので、他のライブラリとの公平性を考慮してダメ扱いとした。(1)はてなブログをはじめよう!mi_kattunさんは、はてなブログを使っています。ブログを報告する引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。