008-quartz定时任务集群下采用gaussDB导致反序列blob字段报错问题

原创 临窗旋墨 2024-10-31 阅读:2566 分类: java后端 专题: 源码阅读 标签: gaussdb,源码

008-quartz定时任务集群下采用gaussDB导致反序列blob字段报错问题

背景

  • springmvc + quartz2.3.2
  • 数据库从oracle迁移到gaussDB

原来的quartz部分表字段为blob,但是迁移到gaussDB下的时候,不兼容,故修改为BYTEA,但是定时任务运行的时候报错:java.lang.NumberFormatException: For input string: "\x",说明是反序列化出了问题。

解决方案

简单翻了下源码,也没有细看,决定直接修改其中的反序列blob字段部分的代码;

1 自定义CustomGaussDBDelegate类,重写getObjectFromBlob方法
复制代码
/**
 * description:
 * gaussDB下反序列blob字段报错:java.lang.NumberFormatException: For input string: "\x"
 *
 * @author Vic.xu
 * @since 2024-10-31 14:42
 */
public class CustomGaussDBDelegate extends StdJDBCDelegate {

    /**
     * 重写获取逻辑,直接rs.getBytes  而不是 rs.getBlob
     */
    @Override
    protected Object getObjectFromBlob(ResultSet rs, String colName)
            throws ClassNotFoundException, IOException, SQLException {
        Object obj = null;
        byte[] bytes = rs.getBytes(colName);
        if (bytes != null && bytes.length > 0) {
            try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
                 ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream)) {
                obj = objectInputStream.readObject();
            } catch (Exception e) {
                return super.getObjectFromBlob(rs, colName);
            }
        }

        return obj;
    }
}

StdJDBCDelegate 原本的代码如下:

java 复制代码
public class StdJDBCDelegate implements DriverDelegate, StdJDBCConstants {       	// 反序列化为对象
       protected Object getObjectFromBlob(ResultSet rs, String colName)
        throws ClassNotFoundException, IOException, SQLException {
        Object obj = null;

        Blob blobLocator = rs.getBlob(colName);
        if (blobLocator != null && blobLocator.length() != 0) {
            InputStream binaryInput = blobLocator.getBinaryStream();

            if (null != binaryInput) {
                if (binaryInput instanceof ByteArrayInputStream
                    && ((ByteArrayInputStream) binaryInput).available() == 0 ) {
                    //do nothing
                } else {
                    ObjectInputStream in = new ObjectInputStream(binaryInput);
                    try {
                        obj = in.readObject();
                    } finally {
                        in.close();
                    }
                }
            }

        }
        return obj;
    }
    //序列化为二进制
    protected void setBytes(PreparedStatement ps, int index, ByteArrayOutputStream baos) throws SQLException {
        ps.setBytes(index, (baos == null) ? new byte[0] : baos.toByteArray());
    }
}

入库时候的序列化没有动,只是修改了获取数据库字段的代码:

rs.getBytes 修改为 rs.getBlob

2 在quartz中配置此Delegate
xml 复制代码
<!-使用自定义delegate,兼容gaussDB->
<prop key="org.quartz.jobStore.driverDelegateClass">cn.xuqiudong.extension.quartz.CustomGaussDBDelegate</prop>

根源还是出在gaussdb上:在 GaussDB 中,BYTEA 是推荐用于二进制数据的字段类型。

评论区

avatar
未登录

暂无评论,来发表第一条评论吧~