使用MyBatis

时间:2019-02-11 22:43:01

标签: mybatis resultset

如何使用MyBatis获得ResultSetMetaData。我无法使用INFORMATION_SCHEMA.columns,因为我有一个包含多个表的复杂动态查询联接。例如,我需要记录数(我可以根据列表大小获得该记录),列列表和每列的数据类型。我浏览了很多,却没有正确的使用方法。

请提出使用TypeHandler或其他一些带有小示例的选项来获取ResultSetMetaData的正确方法吗?

我有2种情况。

  1. 方案1:

    我的查询使用Abinitio QueryIt服务读取文件(它考虑与表相似的文件,并且可以使用SQL查询来读取)。这些文件是从各种上游接收的,而不是固定的一组列。它可以是N列数和任何数据类型。一旦我的查询从文件中读取了数据,它将被发送到UI以显示在Grid中,并具有基于数据类型(整数,双精度,字符串,日期)的格式化输出,以供用户查看。要构建Grid模型,我还需要知道列数和数据类型(用于格式化)。在我知道列数和每列的数据类型之前,我无法构建网格模型。我的映射器的返回类型为List<Map<String, Object>>

  2. 方案2(针对不同的过程):与上述方法类似,查询从多个表中读取数据,而不是根据从UI中选择的条件从文件中读取数据。在此,基于从UI的选择,网格的列数也是动态的。因此,我需要列数和每列的数据类型。返回类型与上面的类型相同。

谢谢。

2 个答案:

答案 0 :(得分:0)

对于复杂的查询,您可以添加自定义映射器。我通常在单独的目录中创建扩展的映射器,因此在再次生成它们时不会被替换。另外,这会将所有自定义SQL保留在一起。

<?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="com.company.core.app.db.mapper.custom.SomethingExtendedMapper">

    <resultMap id="SomethingMap" type="com.company.core.app.db.Something">
        <result column="ID" jdbcType="INTEGER" property="somethingId" />
        <result column="LAST_CHANGE_DATE" jdbcType="DATE"  property="lastChangeDate"
        ...
    </resultMap>

    <select id="getSomething" resultMap="SomethingMap" parameterType="Integer">
        select
        *
        from
        something
        join something else...
        WHERE SOMETHING_ID = #{id}
    </select>
 </mapper>

然后这将是接口:

public interface SomethingExtendedMapper {
    public List<Something> getSomething(@Param("id") Integer id);
}

答案 1 :(得分:0)

您可以编写扩展了TypeHanlder的自定义BaseTypeHandler,这将使您可以访问ResultSetMetaData。我之前已经编写了这样的处理程序,可以将Date转换为LocalDate。这对您的答案有点hacker,因为映射器不会直接返回List<Map<String, Object>>,但是这可能是您要返回的对象的属性。

@MappedTypes(LocalDate.class)
public class DbLocalDateTypeHandler extends BaseTypeHandler<LocalDate> {
      @Override
        public void setNonNullParameter(PreparedStatement ps, int i, LocalDate parameter, JdbcType jdbcType) throws SQLException {
            if (parameter == null) {
                ps.setDate(i, null);
            } else {
                ps.setDate(i, Date.valueOf(parameter));
            }
        }

        @Override
        public LocalDate getNullableResult(ResultSet rs, String columnName) throws SQLException {
            Date date = rs.getDate(columnName);
            if (date != null) {
                return date.toLocalDate();
            }
            return null;
        }

        @Override
        public LocalDate getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
            Date date = rs.getDate(columnIndex);
            if (date != null) {
                return date.toLocalDate();
            }
            return null;
        }

        @Override
        public LocalDate getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
            Date date = cs.getDate(columnIndex);
            if (date != null) {
                return date.toLocalDate();
            }
            return null;
        }
}

然后在您的resultMap中,您只需要引用该处理程序即可:

<result column="CREATE_DATE" jdbcType="DATE" property="createDate" typeHandler="com.company.core.framework.db.DbLocalDateTypeHandler"/>

最后,如果您不需要ResultSetMetaData,可以考虑创建自定义ObjectFactory

例如 How to return an Optional from MyBatis query

有用的MyBatis文档:

http://www.mybatis.org/mybatis-3/configuration.html#typeHandlers

http://www.mybatis.org/mybatis-3/configuration.html#objectFactory