Используйте неявный TypeHandler на основе resultType для select в MyBatis

Я пытаюсь выбрать временную метку в MyBatis и вернуть ее как LocalDateTime (от joda-time).

моя конфигурация отлично работает, если я попытаюсь вернуть результат как java.sql.Timestamp. Я доказал, что мой обработчик типов работает нормально: если я использую класс упаковки с LocalDateTime как только поле и resultMap в файле MyBatis mapper, я получаю правильные результаты.

однако, когда я пытаюсь указать org.joda.time.LocalDateTime as resultType для этого выберите, я всегда получаю null, а если типа обработчик игнорируется.

насколько я понимаю, MyBatis использует typeHandler по умолчанию в случае я resultType="java.sql.Timestamp". Как следствие, я ожидал, что он будет использовать один из typeHandlers, которые я настроил при встрече resultType="org.joda.time.LocalDateTime".

Я что-то пропустил? Есть ли способ использовать мой 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>

1 ответов


чтобы использовать конфигурацию TypeHandler, MyBatis должен знать как тип Java результирующего объекта, так и тип SQL исходного столбца.

здесь мы используем resultType на <select /> таким образом, MyBatis знает тип Java, но он не может знать тип 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>

если вы хотите сэкономить на создании выделенного компонента, вы также можете использовать атрибут type=hashmap на <resultMap /> как было предложено Shobit.

вариант: установите свойство на LocalDateTime

A решение было предложено на Google Groups, который устанавливает непосредственно информацию о 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 является стандартным типом Java для SQL, с реализацией JDBC по умолчанию (ResultSet.getTimestamp(int/String)). Обработчик по умолчанию для MyBatis использует этот getter1 и, следовательно, не нужно любое отображение TypeHandler. Я ожидаю, что это происходит каждый раз, когда вы используете один из обработчиков по умолчанию.


1: это догадка. Требуется цитата!

этот ответ только ждет замены на что-то лучшее. Пожалуйста, внесите свой вклад!