先週に続いて、Mybatisネタです。
3年半前に自分が書いた記事では、何ともおダサい方法で、トリム化を行っていました。
「(4) CHARフィールドのトリムがされない」の部分です。
当時、Mybatisの勉強を始めたばかりだったとはいえ、SQL文でRTRIM関数を行っていました。
これでは、SQLパフォーマンスが悪くなってしまいます。。。
TypeHandlerを使って trim処理をラップする
公式サイトによりますと、次のように書いてありました。
MyBatis が PreparedStatement のパラメーターをセットするとき、 あるいは ResultSet から値を取得するときには、 必ずその Java タイプに対応する TypeHandler が使用されます。
このTypeHandlerと呼ばれる型変換機能を独自に実装してあげることで、Modelに格納する際にtrimやenum変換などの独自処理を追加できるようです。
まずは TypeHandlerクラスの作成です。
StringTrimmingTypeHandler.java
package jp.co.companyName.commons.daos.myTypeHandler; import org.apache.ibatis.type.BaseTypeHandler; import org.apache.ibatis.type.JdbcType; import org.apache.ibatis.type.MappedJdbcTypes; import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Objects; @MappedJdbcTypes(JdbcType.CHAR) public class StringTrimmingTypeHandler extends BaseTypeHandler<String> { @Override public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException { ps.setString(i, trim(parameter)); } @Override public String getNullableResult(ResultSet rs, String columnName) throws SQLException { return trim(rs.getString(columnName)); } @Override public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException { return trim(rs.getString(columnIndex)); } @Override public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { return trim(cs.getString(columnIndex)); } private String trim(String s) { if (Objects.isNull(s)) { return ""; } else { return s.trim(); } } }
mybatis-config.xml
- 次にmybatisの設定で、typeHandlersタグ内に独自に作成したtypeHandlerを設定します。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <typeHandlers> <typeHandler handler="jp.co.companyName.commons.daos.myTypeHandler.StringTrimmingTypeHandler"/> </typeHandlers> <environments default="MAIN"> <environment id="MAIN"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment> </environments> <mappers> <mapper resource="sqls/Sales.xml"/> </mappers> </configuration>
これにより、次のような実際のSQL-SELECT文で、戻り値がresultTypeでMODELを定義した場合に、MODEL内の文字列項目がきちんとtrim化されて格納されていました!! オッケー、オッケー!!
<select id="fetchSalesModel" resultType="SalesModel"> select FIELD_NAME1 as salesDate, FIELD_NAME2 as sectionCode, <!-- 省略 --> from TABLE_NAME where FIELD_NAME3 = #{paramValue1} </select>
それにしても、Mybatisの公式サイトは非常にわかりやすく書かれていて、大変助かります。
感謝ですね!