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

文章来源原创   作者:临窗旋墨   发布时间:2024-10-31   阅读:75   标签:springmvc,源码 分类:mysql 专题:我读[不懂]源码

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方法
  1. /**
  2. * description:
  3. * gaussDB下反序列blob字段报错:java.lang.NumberFormatException: For input string: "\x"
  4. *
  5. * @author Vic.xu
  6. * @since 2024-10-31 14:42
  7. */
  8. public class CustomGaussDBDelegate extends StdJDBCDelegate {
  9. /**
  10. * 重写获取逻辑,直接rs.getBytes 而不是 rs.getBlob
  11. */
  12. @Override
  13. protected Object getObjectFromBlob(ResultSet rs, String colName)
  14. throws ClassNotFoundException, IOException, SQLException {
  15. Object obj = null;
  16. byte[] bytes = rs.getBytes(colName);
  17. if (bytes != null && bytes.length > 0) {
  18. try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
  19. ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream)) {
  20. obj = objectInputStream.readObject();
  21. } catch (Exception e) {
  22. return super.getObjectFromBlob(rs, colName);
  23. }
  24. }
  25. return obj;
  26. }
  27. }

StdJDBCDelegate 原本的代码如下:

  1. public class StdJDBCDelegate implements DriverDelegate, StdJDBCConstants { // 反序列化为对象
  2. protected Object getObjectFromBlob(ResultSet rs, String colName)
  3. throws ClassNotFoundException, IOException, SQLException {
  4. Object obj = null;
  5. Blob blobLocator = rs.getBlob(colName);
  6. if (blobLocator != null && blobLocator.length() != 0) {
  7. InputStream binaryInput = blobLocator.getBinaryStream();
  8. if (null != binaryInput) {
  9. if (binaryInput instanceof ByteArrayInputStream
  10. && ((ByteArrayInputStream) binaryInput).available() == 0 ) {
  11. //do nothing
  12. } else {
  13. ObjectInputStream in = new ObjectInputStream(binaryInput);
  14. try {
  15. obj = in.readObject();
  16. } finally {
  17. in.close();
  18. }
  19. }
  20. }
  21. }
  22. return obj;
  23. }
  24. //序列化为二进制
  25. protected void setBytes(PreparedStatement ps, int index, ByteArrayOutputStream baos) throws SQLException {
  26. ps.setBytes(index, (baos == null) ? new byte[0] : baos.toByteArray());
  27. }
  28. }

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

rs.getBytes 修改为 rs.getBlob

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

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


发表评论

目录