DBでは数値として持った値を、左0埋めして画面に表示していたが、そこを文字列として部分一致検索させることになった。
検索はSpringのSpecificationで、動的なJPQLをCriteriaBuilderで組み立てており、RDBMSの関数を使えないか調べたのでメモ。
やりたいこと
DB(MySQL)では数値で保存した値を左ゼロ埋めし、接頭語をつけて表示している。
数値が1なら、表示は NUM00001
というイメージ。
これを文字列として、部分一致検索できるようにしたい。
対応
MySQLであればLPAD関数で0埋めし、それを接頭語と CONCAT
すればいい。
CONCAT
に対応する操作はCriteriaBuilder#concatで行える。
RDBMSの関数を、JPQLで実行できるか調べたところ、JPA Criteriaで左埋めできないかというそのまんまな質問が、Stack Overflowにあった。
CriteriaBuilder#functionを使えば、RDBMSの関数の実行ができる。
第1引数が関数名、第2引数が関数の戻り値の型、それ以降は可変長引数で関数に渡す値を指定する。
注意点としては、可変長引数の型はExpressionのため、リテラルはCriteriaBuilder#literalでExpressionに変換してやる必要がある。
// 左ゼロ埋めを実施 var leftPad = cb.function( "LPAD", String.class, root.get(ExampleEntity_.seq).as(String.class), cb.literal(5), cb.literal("0") ); // 接頭語とCONCAT var displayValue = cb.concat("NUM", leftPad); // CONCATした文字列を、部分一致検索 cb.like(displayValue, "%" + inputValue + "%")
振り返り
SQL Serverを除いた主要なRDBMSではLPADが使えるようだが、可搬性は下がるので、JPQLの使い方としてはやや邪道か。
DBのテーブル側にカラムを追加して、文字列として保存しておくのが無難かなとは思う。
とはいえ、必要に応じて関数を実行できるようになっているのはありがたい。