mybatis返回值用Map

mybatis 在xml文件中查询数据返回值用map<Sring,Object>集合接收时间类型会被转换为long类型时间戳,此查询为动态查询,表名称和字段都不是固定的(select * from #{tabName})怎样能让查询出来的结果不转换保持在数据库中的格式

引用 皆我百晓生 小程序回复内容作答:
要让查询结果保持在数据库中的格式,你可以使用MyBatis的ResultMap来定义结果的映射关系。在ResultMap中,你可以指定每个字段的类型和转换方式。

首先,在你的xml文件中定义一个ResultMap,其中包含所有可能的字段,例如:

<resultMap id="myResultMap" type="java.util.HashMap">
  <result property="column1" column="column1" javaType="java.sql.Timestamp" jdbcType="TIMESTAMP" />
  <result property="column2" column="column2" javaType="java.util.Date" jdbcType="DATE" />
  <result property="column3" column="column3" javaType="java.math.BigDecimal" jdbcType="DECIMAL" />
  <!-- 其他字段... -->
</resultMap>

在上面的代码中,column1column2column3是你查询语句中的字段名,javaType是希望映射到的Java类型,jdbcType是对应的数据库类型。

然后,在你的查询语句中使用<resultMap>来指定使用该ResultMap,例如:

<select id="yourQuery" resultMap="myResultMap">
  SELECT * FROM ${tabName}
</select>

在上述代码中,yourQuery是你的查询语句的id,${tabName}是你的动态表名。

最后,在Java代码中使用selectOneselectList方法执行查询,接收返回的Map对象,例如:

Map<String, Object> resultMap = sqlSession.selectOne("yourNamespace.yourQuery");

这样,查询结果中的时间类型字段将会保持在数据库中的格式,而不会被转换为长整型时间戳。



import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class DateTimeTypeHandler extends BaseTypeHandler<String> {
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
        // 在这里你可以将 String 类型的时间转换为合适的格式,然后设置到 PreparedStatement 中
        ps.setString(i, parameter);
    }
    @Override
    public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
        // 在这里你可以将从 ResultSet 中获取的时间转换为合适的格式,然后返回
        return rs.getString(columnName);
    }
    @Override
    public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        // 在这里你可以将从 ResultSet 中获取的时间转换为合适的格式,然后返回
        return rs.getString(columnIndex);
    }
    @Override
    public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        // 在这里你可以将从 CallableStatement 中获取的时间转换为合适的格式,然后返回
        return cs.getString(columnIndex);
    }
}

<resultMap id="yourResultMap" type="map">
    <result column="your_date_column" jdbcType="VARCHAR" property="yourDateProperty" typeHandler="com.example.DateTimeTypeHandler"/>
</resultMap>



<resultMap id="myResultMap" type="java.util.HashMap">
  <result property="column1" column="column1" javaType="java.sql.Timestamp" jdbcType="TIMESTAMP" />
  <result property="column2" column="column2" javaType="java.util.Date" jdbcType="DATE" />
  <result property="column3" column="column3" javaType="java.math.BigDecimal" jdbcType="DECIMAL" />
  <!-- 其他字段... -->
</resultMap>

如果你希望在 MyBatis 的 XML 文件中执行动态查询,并且返回的时间类型字段保持数据库中的格式而不转换为 long 类型的时间戳,可以通过在自定义类型处理器中进行特殊处理来实现。

首先,创建一个自定义类型处理器类,例如 MyRawDateTimeTypeHandler

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandler;
import java.sql.*;

public class MyRawDateTimeTypeHandler extends BaseTypeHandler<Object> {
  
  @Override
  public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
    // 如果需要设置参数,根据具体情况进行处理
    // ps.setTimestamp(i, (Timestamp) parameter);
  }

  @Override
  public Object getNullableResult(ResultSet rs, String columnName) throws SQLException {
    // 根据字段名称获取查询结果
    // 根据具体情况将结果进行转换或直接返回
    return rs.getObject(columnName);  // 返回原始类型,不进行转换
  }

  @Override
  public Object getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
    // 根据列索引获取查询结果
    // 根据具体情况将结果进行转换或直接返回
    return rs.getObject(columnIndex);  // 返回原始类型,不进行转换
  }

  @Override
  public Object getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
    // 根据列索引获取查询结果
    // 根据具体情况将结果进行转换或直接返回
    return cs.getObject(columnIndex);  // 返回原始类型,不进行转换
  }
}

在上述示例中,我们的自定义类型处理器 MyRawDateTimeTypeHandler 继承了 BaseTypeHandler<Object>,使用泛型 Object 来表示未知的类型。

getNullableResult 方法中,我们直接返回原始的查询结果,而不进行类型转换。

接下来,将该自定义类型处理器与动态查询中的时间类型字段关联。在 <resultMap><result> 标签中,设置 jdbcType="OTHER" 并指定自定义类型处理器。

例如,如果你的动态查询如下所示:

<select id="dynamicQuery" resultType="java.util.Map">
  SELECT *
  FROM ${tabName}
</select>

可以将其修改如下:

<select id="dynamicQuery" resultType="java.util.Map">
  <resultMap type="java.util.Map">
    <result column="*" jdbcType="OTHER" typeHandler="com.example.MyRawDateTimeTypeHandler"/>
  </resultMap>
  SELECT *
  FROM ${tabName}
</select>

在上述示例中,我们在 <resultMap> 中配置了针对所有列的结果映射,使用 jdbcType="OTHER" 指定了未知的类型,并通过 typeHandler 属性将自定义类型处理器 MyRawDateTimeTypeHandler 关联起来。

这样,在执行动态查询时,时间类型字段将会以原始的格式保存在结果的 Map 中,而不会被转换为 long 类型的时间戳。

请注意,上述示例是针对动态查询的情况,并且假设返回的结果是一个 Map,具体的实现方式和细节可能会因你的实际需求而有所不同,你可以根据自己的情况进行调整和修改。

该回答引用chatgpt
在 MyBatis 中,当使用 map<Sring,Object> 集合接收查询结果时,MyBatis 会自动将结果集中的时间类型转换为 long 类型时间戳。如果您需要保持时间类型的原始格式,可以尝试使用以下方法:

  1. 自定义 TypeHandler

可以自定义一个 TypeHandler 来处理时间类型的转换。具体步骤如下:

  • 实现 TypeHandler 接口,重写 setParameter、getResult 等方法,将时间类型转换为字符串或将字符串转换为时间类型。
  • 在 MyBatis 的配置文件中注册自定义的 TypeHandler。

这种方法比较灵活,可以通过代码自由控制时间类型的转换方式,但需要编写一些额外的代码。

  1. 使用 resultMap 映射查询结果

可以在 SQL 映射文件中使用 resultMap 标签来映射查询结果。具体步骤如下:

  • 在 resultMap 标签中定义每个字段的映射关系,包括字段名、Java 类型、JDBC 类型等。
  • 在 select 标签中使用 resultMap 属性引用定义好的 resultMap。

这种方法相对简单,不需要编写额外的代码。如果查询结果中的字段类型比较多,定义 resultMap 可以提高代码的可读性和维护性。

无论采用哪种方法,为了保留原始的时间格式,需要在定义字段映射关系时,将对应的 JDBC 类型设置为 TIMESTAMP 或 DATE,而不是设置为 NUMERIC 或其他类型。例如:

<resultMap id="resultMap" type="java.util.Map">
  <result column="create_time" property="createTime" jdbcType="TIMESTAMP"/>
  <result column="update_time" property="updateTime" jdbcType="TIMESTAMP"/>
</resultMap>

<select id="queryData" resultMap="resultMap">
  select * from #{tabName}
</select>

这样,在使用 map<Sring,Object> 集合接收查询结果时,MyBatis 就不会将时间类型转换为 long 类型时间戳了,而是保留原始的类型。