解决:oracle+myBatis ResultMap 类型为 map 时,表字段类型有 Long/Blob/Clob 时报错

前言:最近在做一个通用查询单表的组件,所以 sql 的写法就是 select *,然后 resultType="map" 。如果数据库中的表里有字段类型为 Long 等类型时,mybatis 在执行 sql 时会报错,如果表中有 Blob、Clob 类型在转 json 是也会报错,而且我这里也需要将这几种类型都转为 String 类型到前端。

long 类型 sql 报错:

Blob/Clob 转 json 报错:

解决方案:

自定义 typeHandle 来统一处理数据库这些特殊的字段。

这里 typeHandle 里面使用注解配置 JdbcType 和 JavaType。这两个注解的定义是:

  • @MappedTypes 定义的是 JavaType 类型,可以指定哪些 Java 类型被拦截。
  • @MappedJdbcTypes 定义的是 JdbcType 类型,它需要满足枚举类 org.apache.ibatis.type.JdbcType 所列的枚举类型。

代码如下:

myBatis 的配置文件中加入:

    <typeHandlers>
        <!--自定义处理 JdbcType.TIMESTAMP 和 java Object(Data)-->
        <typeHandler handler="com.yule.querydb.typehandler.MyObjectTimestampTypeHandle"/>
        <!--自定义处理 JdbcType.Clob 和 java Object(String)-->
        <typeHandler handler="com.yule.querydb.typehandler.MyObjectClobTypeHandle"/>
        <!--自定义处理 JdbcType.Blob 和 java Object(String)-->
        <typeHandler handler="com.yule.querydb.typehandler.MyObjectBlobTypeHandle"/>
        <!--自定义处理 JdbcType.LONGVARCHAR 和 java Object(String)-->
        <typeHandler handler="com.yule.querydb.typehandler.MyObjectLongTypeHandle"/>
    </typeHandlers>

这些 typeHandle 类源码:

package com.yule.querydb.typehandler;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;

import java.io.StringReader;
import java.sql.*;

/**
 * 自定义处理 JdbcType.Blob 和 java Object(String)
 * 处理转 json 报错,将 oracle.sql.Clob 类型转为 String 类型
 * copy org.apache.ibatis.type.ClobTypeHandler 类的处理
 * @author yule
 * @date 2018/10/9 17:57
 */
@MappedTypes({Object.class})
@MappedJdbcTypes(value = {JdbcType.CLOB})
public class MyObjectClobTypeHandle extends BaseTypeHandler<Object> {

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
        String parameterStr = (String) parameter;
        StringReader reader = new StringReader(parameterStr);
        ps.setCharacterStream(i, reader, parameterStr.length());
    }

    @Override
    public Object getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String value = "";
        Clob clob = rs.getClob(columnName);
        if(clob != null) {
            int size = (int)clob.length();
            value = clob.getSubString(1L, size);
        }

        return value;
    }

    @Override
    public Object getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String value = "";
        Clob clob = rs.getClob(columnIndex);
        if(clob != null) {
            int size = (int)clob.length();
            value = clob.getSubString(1L, size);
        }

        return value;
    }

    @Override
    public Object getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String value = "";
        Clob clob = cs.getClob(columnIndex);
        if(clob != null) {
            int size = (int)clob.length();
            value = clob.getSubString(1L, size);
        }

        return value;
    }

}
MyObjectBlobTypeHandle
package com.yule.querydb.typehandler;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;

import java.io.StringReader;
import java.sql.*;

/**
 * 自定义处理 JdbcType.Blob 和 java Object(String)
 * 处理转 json 报错,将 oracle.sql.Blob 类型转为 String 类型
 * copy org.apache.ibatis.type.BlobTypeHandler 类的处理
 * @author yule
 * @date 2018/10/9 17:57
 */
@MappedTypes({Object.class})
@MappedJdbcTypes(value = {JdbcType.BLOB})
public class MyObjectBlobTypeHandle extends BaseTypeHandler<Object> {

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
        byte[] parameterByteArray = (byte[]) parameter;
        String parameterStr = new String(parameterByteArray);
        StringReader reader = new StringReader(parameterStr);
        ps.setCharacterStream(i, reader, parameterStr.length());
    }

    @Override
    public Object getNullableResult(ResultSet rs, String columnName) throws SQLException {
        Blob blob = rs.getBlob(columnName);
        byte[] returnValue = null;
        if(null != blob) {
            returnValue = blob.getBytes(1L, (int)blob.length());
        }

        return returnValue == null ? "" : new String(returnValue);
    }

    @Override
    public Object getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        Blob blob = rs.getBlob(columnIndex);
        byte[] returnValue = null;
        if(null != blob) {
            returnValue = blob.getBytes(1L, (int)blob.length());
        }

        return returnValue == null ? "" : new String(returnValue);
    }

    @Override
    public Object getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        Blob blob = cs.getBlob(columnIndex);
        byte[] returnValue = null;
        if(null != blob) {
            returnValue = blob.getBytes(1L, (int)blob.length());
        }

        return returnValue == null ? "" : new String(returnValue);
    }
}
MyObjectLongTypeHandle
package com.yule.querydb.typehandler;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;

import java.io.StringReader;
import java.sql.*;

/**
 * 自定义处理 JdbcType.LONGVARCHAR 和 java Object(String)
 * 处理转 mybatis 执行返回map的sql 报错,将 oracle Long 型转为 String 类型
 * @author yule
 * @date 2018/10/9 19:18
 */
@MappedTypes({Object.class, String.class})
@MappedJdbcTypes(value = {JdbcType.LONGVARCHAR})
public class MyObjectLongTypeHandle extends BaseTypeHandler<Object> {
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
        String parameterStr = (String) parameter;
        StringReader reader = new StringReader(parameterStr);
        ps.setCharacterStream(i, reader, parameterStr.length());
    }

    @Override
    public Object getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String str = rs.getString(columnName);
        return str != null ? str : "";
    }

    @Override
    public Object getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String str = rs.getString(columnIndex);
        return str != null ? str : "";
    }

    @Override
    public Object getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String str = cs.getString(columnIndex);
        return str != null ? str : "";
    }
}


原文地址:https://www.cnblogs.com/yuxiaole/p/9775389.html

时间: 2024-07-31 18:36:56

解决:oracle+myBatis ResultMap 类型为 map 时,表字段类型有 Long/Blob/Clob 时报错的相关文章

Java实体类的属性类型与mysql数据库表字段类型对应表

感谢原文博主https://blog.csdn.net/Hyo555/article/details/81943340 还有些经常用到的mysql语句 -- 新增表结构 DROP TABLE IF EXISTS `servicnn`; CREATE TABLE `servin` ( `id` int(11) NOT NULL AUTO_INCREMENT, `operation_unit` varchar(100) DEFAULT NULL COMMENT '运', `create_time`

mybatis返回集合类型为map时

Mybatis返回值为map时 使用条件:当映射属性超出了一个Bean时: 第一步: 第二步: 第三步: 此方式只能当返回值为lIst集合时. 原文地址:https://www.cnblogs.com/xiaofengshan/p/12347989.html

解决Oracle 11g在用EXP导出时,空表不能导出

一.问题原因:     11G中有个新特性,当表无数据时,不分配segment,以节省空间     1.insert一行,再rollback就产生segment了. 该方法是在在空表中插入数据,再删除,则产生segment.导出时则可导出空表. 2.设置deferred_segment_creation 参数 show parameter deferred_segment_creation NAME                                 TYPE        VALU

修改非空表字段类型Oracle

执行以下语句报"要修改数据类型,则要更改的列必须为空"       alter table 表名 modify (目标字段 varchar2(100)); 解决步骤: 第一步,在表中加一个临时字段       alter table 表名 add 临时字段 目标字段原来的类型; 第二步,将目标字段的值付给临时字段,并将目标字段置空       update 表名 set 临时字段=目标字段,目标字段=null; 第三步,修改目标类型       alter table 表名  modi

MySQL建表字段类型

1.数据库:在MySQL中,要存储数据,必须从数据库开始,因此首先要创建数据库,但由于学校的MySQL服务器对学生数据帐号有限止,学生不得创建数据库,故每个学生的帐号中已事先由信息中心为大家建立了一个名为帐号名的数据库.但我们必须了解创建数据库的语句为CREATE DATABASE <数据库名>2.数据表:是构成数据库的一个基本单位,在一个数据库中用户可以建立多张数据表.这是我们有权力建立的.3.数据表结构:创建一个数据表的第一步即为创建数据表结构,在数据表结构中的内容包括:有几个字段,每个字

资源表 表字段类型大全

在我们对资源表进行操作也就是,添加表时JEPLUS平台会自动给我们默认的提供了表字段的类型,今天我来详细介绍下表字段类型大全,以及对应数据库到底是什么类型. 一.效果展示 二.准备工作 1.JEPLUS平台5.0.0.2(我是刚升级之后的版本,5.0以上的版本都是可以实现这个功能) 2.数据库MySql 5.7 三.实现步骤 1.数据库建表时的类型对应,我们在平台上创建的表字段选择的类型对应的数据库类型是什么. 我们对应到数据库的真实类型是什么 2.当我们选择的类型为整数时对应的数据库类型 在数

资源表 表字段类型大全—JEPLUS快速开发平台

在我们对资源表进行操作也就是,添加表时JEPLUS平台会自动给我们默认的提供了表字段的类型,今天我来详细介绍下表字段类型大全,以及对应数据库到底是什么类型. 一.效果展示 二.准备工作 1.JEPLUS平台5.0.0.2(我是刚升级之后的版本,5.0以上的版本都是可以实现这个功能) 2.数据库MySql 5.7 三.实现步骤 1.数据库建表时的类型对应,我们在平台上创建的表字段选择的类型对应的数据库类型是什么. 我们对应到数据库的真实类型是什么 2.当我们选择的类型为整数时对应的数据库类型 在数

通过jdbc获取数据库中的表结构 主键 各个表字段类型及应用生成实体类

http://www.cnblogs.com/lbangel/p/3487796.html package cn.test; import java.io.File;import java.io.FileOutputStream;import java.sql.Connection;import java.sql.DatabaseMetaData;import java.sql.DriverManager;import java.sql.ResultSet;import java.text.Si

SQLSERVER创建该存储过程时不会出错,但是执行存储过程时报错

创建该存储过程时,不会出错,但是执行存储过程时,会报出下面这样的错误 这是因为在存储过程创建时,它先做语法检查,如果通过了语法检查,它会尝试解析它包含的对象名,如果存在也会解析该对象引用的对象是否存在.如果引用的对象名不存在,解析会在存储过程首次执行时触发.即在首次执行存储过程时,查询处理器从 sys.sql_modules 目录视图中读取该存储过程的文本,并检查该过程所使用的对象名称是否存在.这一过程称为延迟名称解析,因为存储过程引用的表对象不需要在创建该存储过程时就存在,而只需在执行该存储过