# 概要
業務でMyBatisを使っているのですがjavaのバージョンを8に上げるにあたり、折角Date and Time API (JSR 310) で日付関連が便利になったと言われているので、DTOのフィールドをLocalDateTimeにしようとして調べた結果です。
MyBatisの公式ドキュメントに書いてあったので簡単にできました。
table (mysql)
CREATE TABLE `sample` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`created` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
結果を格納するDTO
sample.domain.SampleDto.java
import java.time.LocalDateTime;
import lombok.Data;
@Data
public class SampleDto {
private int id;
private LocalDateTime created;
}
このcreated
をSQLの結果とマッピングしたい。
## TypeHandler
どうやらorg.apache.ibatis.type.TypeHandler
かorg.apache.ibatis.type.BaseTypeHandler
を実装してjdbcのクラスとマッピングすると良いよって事らしい。
今回はBaseTypeHandlerを実装してみました。
sample.mybatis.handlers.LocalDateTimeTypeHandler.java
@MappedTypes(LocalDateTime.class)
public class LocalDateTimeTypeHandler
extends BaseTypeHandler<LocalDateTime> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, LocalDateTime parameter, JdbcType jdbcType) throws SQLException {
ps.setTimestamp(i, Timestamp.valueOf(parameter));
}
@Override
public LocalDateTime getNullableResult(ResultSet rs, String columnName) throws SQLException {
Timestamp timestamp = rs.getTimestamp(columnName);
if (timestamp == null) {
return null;
} else {
return timestamp.toLocalDateTime();
}
}
@Override
public LocalDateTime getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
Timestamp timestamp = rs.getTimestamp(columnIndex);
if (timestamp == null) {
return null;
} else {
return timestamp.toLocalDateTime();
}
}
@Override
public LocalDateTime getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
Timestamp timestamp = cs.getTimestamp(columnIndex);
if (timestamp == null) {
return null;
} else {
return timestamp.toLocalDateTime();
}
}
}
## mybatis-config.xml
mybatis-config.xmlに作成したTypeHandlerを探すように設定を追加します。
mybatis-config.xml
<configuration>
<typeHandlers>
<typeHandler handler="sample.mybatis.handlers.LocalDateTimeTypeHandler"/>
</typeHandlers>
</configuration>
または
mybatis-config.xml
<configuration>
<typeHandlers>
<package name="sample.mybatis.handlers"/>
</typeHandlers>
</configuration>
同一パッケージにまとめて実装してpackage指定する方が楽かなぁ。
Mapper
public interface SampleMapper {
@Select("SELECT * FROM sample)
List<SampleDto> selectAll();
@Insert("insert into sample (created) values ( #{created} )")
@SelectKey(before = false, keyProperty = "id", resultType = int.class, statement = { "select last_insert_id()" })
int insert(SampleDto sampleDto);
}
あとは普通にMapper使うだけで検索・登録ともにDBとマッピングされます。