java 在 MyBatis 中使用基于 resultType 的隐式 TypeHandler 进行选择

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30307031/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 16:52:10  来源:igfitidea点击:

Use an implicit TypeHandler based on resultType for select in MyBatis

javajodatimemybatis

提问by Chop

I am trying to select a timestamp in MyBatis and return it as a LocalDateTime (from joda-time).

我试图在 MyBatis 中选择一个时间戳并将其作为 LocalDateTime(来自 joda-time)返回。

My configuration works fine if I try to return the result as a java.sql.Timestamp. I proved my type handler works fine: if I use a wrapping class with a LocalDateTimeas only field and a resultMap in the MyBatis mapper file, I get the correct results.

如果我尝试将结果作为java.sql.Timestamp. 我证明我的类型处理程序工作正常:如果我LocalDateTime在 MyBatis 映射器文件中使用带有as only 字段和 resultMap的包装类,我会得到正确的结果。

However, when I try specifying the org.joda.time.LocalDateTimeas resultTypefor this select, I always get null, as if the type handler is ignored.

但是,当我尝试为此选择指定org.joda.time.LocalDateTimeas 时resultType,我总是得到null,就好像忽略了类型处理程序。

It is my understanding that MyBatis uses a default typeHandler in the case I have resultType="java.sql.Timestamp". As a consequence, I expected it to use one of the typeHandlers I configured when meeting resultType="org.joda.time.LocalDateTime".

我的理解是 MyBatis 在我有resultType="java.sql.Timestamp". 因此,我希望它使用我在会议时配置的类型处理程序之一resultType="org.joda.time.LocalDateTime"

Did I miss something? Is there a way to make use of my typeHandler or am I forced to make a wrapper class and resultMap? This is my fallback-to solution but I would like to avoid it if possible.

我错过了什么?有没有办法利用我的 typeHandler 或者我被迫制作一个包装类和 resultMap?这是我的后备解决方案,但如果可能,我想避免它。

Any help appreciated. Thank you.

任何帮助表示赞赏。谢谢你。

mybatis-config.xml

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

NotifMailDao.java

import org.joda.time.LocalDateTime;

public interface NotifMailDao {

    LocalDateTime getLastNotifTime(String userId);
}

NotifMailDao.xml

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>

采纳答案by Chop

To use the TypeHandler configuration, MyBatis needs to know both the Java type of the resulting object and the SQL type of the source column.

要使用 TypeHandler 配置,MyBatis 需要知道结果对象的 Java 类型和源列的 SQL 类型。

Here we use a resultTypein the <select />so MyBatis knows the Java type, but it cannot know the SQL type if we do not set it. The only way is to use a <resultMap />.

这里我们使用 a resultType<select />所以 MyBatis 知道 Java 类型,但是如果我们不设置它就无法知道 SQL 类型。唯一的方法是使用<resultMap />.

The solution

解决方案

You need to create a Bean with a single field containing the object you want to return (let us call this field time) and use a <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>

If you wish to spare the creation of dedicated bean, you can also use the attribute type=hashmapon your <resultMap />as suggested by Shobit.

如果您不想创建专用 bean,您也可以按照Shobit 的建议type=hashmap在您的设备上使用该属性。<resultMap />

Variant: set the property on the LocalDateTime

变体:设置属性 LocalDateTime

A solutionhas been proposed on Google Groups, which sets directly the information on the LocalDateTime.

Google Groups 上已经提出了一个解决方案,它直接在LocalDateTime.

My understanding of it (please comment if I am wrong) is that it sets a property of the LocalDateTime. I will not vouch for it as I do not find the corresponding in the API doc(and I have not tested it) but feel free to use it if you deem it better.

我对它的理解(如果我错了请评论)是它设置了LocalDateTime. 我不会保证它,因为我在API 文档中没有找到相应的内容(我还没有测试过),但如果你认为它更好,请随时使用它。

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

Why it works with java.sql.Timestamp

为什么它与 java.sql.Timestamp

Timestampis a standard Java type for SQL, with a default JDBC implementation (ResultSet.getTimestamp(int/String)). The default handler for MyBatis uses this getter1and therefore does not need any TypeHandler mapping. I expect this occurs every time you use one of the default handlers.

Timestamp是 SQL 的标准 Java 类型,具有默认的 JDBC 实现 ( ResultSet.getTimestamp(int/String))。MyBatis 的默认处理程序使用这个 getter 1,因此不需要任何 TypeHandler 映射。我希望每次使用默认处理程序之一时都会发生这种情况。



1: This is a hunch. Citation required!

1:这是一种预感。需要引用!

This answer only awaits to be replaced with something better. Please contribute!

这个答案只等着被更好的东西取代。请贡献!