web-dev-qa-db-ja.com

MyBatisでの選択にはresultTypeに基づく暗黙のTypeHandlerを使用します

MyBatisでタイムスタンプを選択し、それをLocalDateTime(joda-timeから)として返そうとしています。

結果をJava.sql.Timestampとして返そうとすると、構成は正常に機能します。タイプハンドラーが正常に機能することを証明しました。MyBatisマッパーファイルでLocalDateTimeのみのフィールドとresultMapを使用してラッピングクラスを使用すると、正しい結果が得られます。

ただし、この選択でorg.joda.time.LocalDateTimeresultTypeとして指定しようとすると、タイプハンドラーが無視されているかのように、常にnullが取得されます。

私がresultType="Java.sql.Timestamp"を持っている場合、MyBatisはデフォルトのtypeHandlerを使用することを理解しています。結果として、resultType="org.joda.time.LocalDateTime"に会うときに構成したtypeHandlerの1つを使用することを期待していました。

私は何か見落としてますか? typeHandlerを利用する方法はありますか、それともラッパークラスとresultMapを作成する必要がありますか?これは私のフォールバックソリューションですが、可能であれば避けたいと思います。

助けていただければ幸いです。ありがとうございました。

mybatis-config.xml

<?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 javaType="org.joda.time.LocalDate" jdbcType="DATE" handler="...LocalDateTypeHandler"/>
        <typeHandler javaType="org.joda.time.LocalDateTime" jdbcType="TIMESTAMP" handler="...LocalDateTimeTypeHandler"/>
    </typeHandlers>
</configuration>

NotifMailDao.Java

import org.joda.time.LocalDateTime;

public interface NotifMailDao {

    LocalDateTime getLastNotifTime(String userId);
}

NotifMailDao.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="lu.bgl.notif.mail.dao.NotifMailDao">

    <select id="getLastNotifTime" resultType="org.joda.time.LocalDateTime">
        SELECT current_timestamp
        AS last_time
        FROM DUAL
    </select>
</mapper>
12
Chop

TypeHandler構成を使用するには、MyBatisは結果のオブジェクトのJavaタイプとソース列のSQLタイプの両方を知っている必要があります。

ここでは、_<select />_でresultTypeを使用しているため、MyBatisはJava型を認識しますが、SQL型を設定しないと、SQL型を認識できません。唯一の方法_<resultMap />_を使用することです。

ソリューション

返したいオブジェクトを含む単一のフィールドでBeanを作成し(このフィールドをtimeと呼びましょう)、_<resultMap />_を使用する必要があります。

_<select id="getLastNotifTime" resultMap="notifMailResultMap">
_

_<resultMap id="mapLastTime" type="MyWrapperBean">
    <result property="time" column="my_sql_timestamp" javaType="org.joda.time.LocalDateTime"
        jdbcType="TIMESTAMP" />
</resultMap>
_

専用Beanの作成を惜しまない場合は、 Shobit で提案されているように、_type=hashmap_で属性_<resultMap />_を使用することもできます。

バリアント:LocalDateTimeにプロパティを設定します

solution がGoogleグループで提案されており、LocalDateTimeに直接情報を設定します。

それについての私の理解(私が間違っている場合はコメントしてください)は、それがLocalDateTimeのプロパティを設定するということです。 API doc に対応するものが見つからないため(テストは行っていません)、保証はしませんが、より適切と思われる場合は自由に使用してください。

_<resultMap id="mapLastTime" type="org.joda.time.LocalDateTime">
    <result property="lastTime" column="my_sql_timestamp" javaType="org.joda.time.LocalDateTime"
        jdbcType="TIMESTAMP" />
</resultMap>
_

_Java.sql.Timestamp_で動作する理由

TimestampはSQLの標準Javaタイプで、デフォルトのJDBC実装があります( ResultSet.getTimestamp(int/String) )。MyBatisのデフォルトハンドラーこのゲッターを使用します1 したがって、TypeHandlerマッピングは必要ありません。これは、デフォルトのハンドラーの1つを使用するたびに発生すると思います。


1:これは予感です。引用が必要です!

この答えは、より良いものに置き換えられるのを待っているだけです。貢献してください!

3
Chop