型変換処理
JDBCでは使用できるクラスタイプは限られているため、java.time.LocalDate
などはバインドパラメータとして使用する場合は java.sql.Date
に変換しておく必要があります。
しかし、エンティティクラスなどをパラメータとして直接使用したいときは、わざわざ変換するのが面倒なときがあります。
そのようなときは、変換規則を登録しておくことで、そのままパラメータとして渡すことができます。
例として、java.time.LocalDate
の変換処理を示します。
1. SqlTemplateValueType の実装
型変換処理は、 SqlTemplateValueType
を実装します。
-
getBindVariableValue(...)
にて、バインドパラメータの値を変換します。-
下記の例では、
java.util.Date
に変換する例ですが、SpringのJdbcTemplateを使用する場合は、SqlParameterValue に変換してもかまいません。 -
その場合、
SqlParameterValue(Types.BLOB, new SqlLobValue(value, lobHandler));
のようにラージオブジェクトも処理ができます。
-
-
getEmbeddedValue(...)
にて、文字列置換のパラメータを変換します。- デフォルト実装では、
#toString()
メソッドが呼ばれるので必要であれば実装します。
- デフォルト実装では、
public class LocalDateType implements SqlTemplateValueType<LocalDate> { // バインドパラメータの変換処理 @Override public Object getBindVariableValue(LocalDate value) throws SqlTypeConversionException { Date sqlValue = (value != null ? Date.valueOf(value) : null); return sqlValue; } // 文字列置換のパラメータの変換処理 // ※ default実装されており、必要なときにオーバーライドして実装します。 @Override public String getEmbeddedValue(LocalDate value) { if(value == null) { return null; } DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd"); return value.format(formatter); } }
2. SqlTemplateValueType の登録
SqlTemplateValueType
は、SqlTemplateContext#registerValueType(...)
にて登録します。
クラスタイプを指定することで、すべての LocalDate
に対して変換が適用されます。
MapSqlTemplateContext templateContext = new MapSqlTemplateContext(); // パラメータ変数の設定 templateContext.setVariable("birthday", LocalDate.of(2020, 10, 1)); // 変換処理の登録 templateContext.registerValueType(LocalDate.class, new LocalDateType());
パラメータ名によって変換処理を変更したい場合は、パラメータ名を指定して登録します。
- クラスタイプの指定とパラメータ名の指定の両方が登録されている場合、パラメータ名の方が優先されます。
MapSqlTemplateContext templateContext = new MapSqlTemplateContext(); // パラメータ変数の設定 templateContext.setVariable("birthday", LocalDate.of(2020, 10, 1)); // 変換処理の登録(birthdayのみに適用されます) templateContext.registerValueType("birthday", LocalDate.class, new LocalDateType());
ネストしたパラメータの場合は、パスを指定します。
- ネストした要素がリスト/配列/マップの場合は、パラメータ名は
data[1].value
のようにインデックスやキー名を指定していても、変換処理の登録はdata.value
のインデックスやキー名を省略した形式で登録してください。
MapSqlTemplateContext templateContext = new MapSqlTemplateContext(); // ネストしたパラメータ変数の設定 Person pserson = new Person(); pserson.setBirthday(LocalDate.of(2020, 10, 1)); templateContext.setVariable("person", pserson); // 変換処理の登録(person.birthdayのみに適用されます) templateContext.registerValueType("person.birthday", LocalDate.class, new LocalDateType());
3. 列挙型の変換処理
列挙型の実態は java.lang.Enum
の具象クラスであるため、全ての列挙型に対する変換処理は次のように実装します。
// 汎用的な列挙型をordinalに変換する処理 public class EnumOrdinalType<T extends Enum<T>> implements SqlTemplateValueType<T> { @Override public Object getBindVariableValue(T value) throws SqlTypeConversionException { Integer sqlValue = (value != null ? value.ordinal() : null); return sqlValue; } }
変換処理の登録は、 Enum.class
に対して登録します。
// 列挙型の定義 enum Color {RED, BLUE, YELLOW}; // パラメータ変数の設定 MapSqlTemplateContext templateContext = new MapSqlTemplateContext(); templateContext.setVariable("color", Color.RED); // 変換処理の登録(全ての列挙型に適用されます) templateContext.registerValueType(Enum.class, new EnumOrdinalType());