XXL-JOB 适配 GAUSSDB, 报 ERROR: column “job_data“ is of type blob but expression is of type bytea

调用任务时抛异常:

xxl-job-admin [com.xxl.job.admin.service.impl.XxlJobServiceImpl]-[http-nio-8080-exec-10]-[triggerJob]-[290]-[ERROR] Couldn't store trigger 'DEFAULT.MT_63hwu012jht6' for '35.546' job:[*******] ERROR: column "job_data" is of type blob but expression is of type bytea
  Hint: You will need to rewrite or cast the expression.
  Position: 323
  Where: referenced column: job_data
org.quartz.JobPersistenceException: Couldn't store trigger 'DEFAULT.MT_63hwu012jht6' for '35.546' job:[**********] ERROR: column "job_data" is of type blob but expression is of type bytea
  Hint: You will need to rewrite or cast the expression.
  Position: 323
  Where: referenced column: job_data [See nested exception: com.huawei.gaussdb.jdbc.util.PSQLException: [**********] ERROR: column "job_data" is of type blob but expression is of type bytea
  Hint: You will need to rewrite or cast the expression.
  Position: 323
  Where: referenced column: job_data]
        at org.quartz.impl.jdbcjobstore.JobStoreSupport.storeTrigger(JobStoreSupport.java:1228)
        at org.quartz.impl.jdbcjobstore.JobStoreSupport$4.executeVoid(JobStoreSupport.java:1164)
        at org.quartz.impl.jdbcjobstore.JobStoreSupport$VoidTransactionCallback.execute(JobStoreSupport.java:3765)
        at org.quartz.impl.jdbcjobstore.JobStoreSupport$VoidTransactionCallback.execute(JobStoreSupport.java:3763)
        at org.quartz.impl.jdbcjobstore.JobStoreCMT.executeInLock(JobStoreCMT.java:245)
        at org.quartz.impl.jdbcjobstore.JobStoreSupport.storeTrigger(JobStoreSupport.java:1160)
        at org.quartz.core.QuartzScheduler.triggerJob(QuartzScheduler.java:1156)
        at org.quartz.impl.StdScheduler.triggerJob(StdScheduler.java:341)
        at com.xxl.job.admin.core.schedule.XxlJobDynamicScheduler.triggerJob(XxlJobDynamicScheduler.java:358)
        at com.xxl.job.admin.service.impl.XxlJobServiceImpl.triggerJob(XxlJobServiceImpl.java:287)
        at com.xxl.job.admin.controller.JobInfoController.triggerJob(JobInfoController.java:102)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
        at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133)
        at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
        at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967)
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
        at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:515)
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:583)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:212)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:156)
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:181)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:156)
        at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:181)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:156)
        at com.xxl.job.admin.filter.xss.XSSFilter.doFilter(XSSFilter.java:36)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:181)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:156)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:168)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:483)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:130)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)
        at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:679)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:346)
        at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:617)
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:934)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1690)
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
        at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
        at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63)
        at java.lang.Thread.run(Thread.java:748)
Caused by: com.huawei.gaussdb.jdbc.util.PSQLException: [*******] ERROR: column "job_data" is of type blob but expression is of type bytea
  Hint: You will need to rewrite or cast the expression.
  Position: 323
  Where: referenced column: job_data
        at com.huawei.gaussdb.jdbc.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:3315)
        at com.huawei.gaussdb.jdbc.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:3002)
        at com.huawei.gaussdb.jdbc.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:446)
        at com.huawei.gaussdb.jdbc.jdbc.PgStatement.runQueryExecutor(PgStatement.java:657)
        at com.huawei.gaussdb.jdbc.jdbc.PgStatement.executeInternal(PgStatement.java:613)
        at com.huawei.gaussdb.jdbc.jdbc.PgStatement.execute(PgStatement.java:445)
        at com.huawei.gaussdb.jdbc.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:165)
        at com.huawei.gaussdb.jdbc.jdbc.PgPreparedStatement.executeUpdate(PgPreparedStatement.java:127)
        at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeUpdate(NewProxyPreparedStatement.java:384)
        at org.quartz.impl.jdbcjobstore.StdJDBCDelegate.insertTrigger(StdJDBCDelegate.java:1093)
        at org.quartz.impl.jdbcjobstore.JobStoreSupport.storeTrigger(JobStoreSupport.java:1225)
        ... 56 more

Quartz 默认使用 org.quartz.impl.jdbcjobstore.StdJDBCDelegate 来处理 SQL 语句,报错的是blob

字段的设置方式

    public int insertTrigger(Connection conn, OperableTrigger trigger, String state,
            JobDetail jobDetail) throws SQLException, IOException {

        ByteArrayOutputStream baos = null;
        if(trigger.getJobDataMap().size() > 0) {
            baos = serializeJobData(trigger.getJobDataMap());
        }
        
        PreparedStatement ps = null;

        int insertResult = 0;

        try {
            ps = conn.prepareStatement(rtp(INSERT_TRIGGER));
            ps.setString(1, trigger.getKey().getName());
            ps.setString(2, trigger.getKey().getGroup());
            ps.setString(3, trigger.getJobKey().getName());
            ps.setString(4, trigger.getJobKey().getGroup());
            ps.setString(5, trigger.getDescription());
            if(trigger.getNextFireTime() != null)
                ps.setBigDecimal(6, new BigDecimal(String.valueOf(trigger
                        .getNextFireTime().getTime())));
            else
                ps.setBigDecimal(6, null);
            long prevFireTime = -1;
            if (trigger.getPreviousFireTime() != null) {
                prevFireTime = trigger.getPreviousFireTime().getTime();
            }
            ps.setBigDecimal(7, new BigDecimal(String.valueOf(prevFireTime)));
            ps.setString(8, state);
            
            TriggerPersistenceDelegate tDel = findTriggerPersistenceDelegate(trigger);
            
            String type = TTYPE_BLOB;
            if(tDel != null)
                type = tDel.getHandledTriggerTypeDiscriminator();
            ps.setString(9, type);
            
            ps.setBigDecimal(10, new BigDecimal(String.valueOf(trigger
                    .getStartTime().getTime())));
            long endTime = 0;
            if (trigger.getEndTime() != null) {
                endTime = trigger.getEndTime().getTime();
            }
            ps.setBigDecimal(11, new BigDecimal(String.valueOf(endTime)));
            ps.setString(12, trigger.getCalendarName());
            ps.setInt(13, trigger.getMisfireInstruction());
            setBytes(ps, 14, baos);
            ps.setInt(15, trigger.getPriority());
            
            insertResult = ps.executeUpdate();
            
            if(tDel == null)
                insertBlobTrigger(conn, trigger);
            else
                tDel.insertExtendedTriggerProperties(conn, trigger, state, jobDetail);
            
        } finally {
            closeStatement(ps);
        }

        return insertResult;
    }

就是这一句

 setBytes(ps, 14, baos);

处理方式和 Oracle 的类似,我们就从 OracleDelegate 继承个类来实现

package org.quartz.impl.jdbcjobstore.oracle.gaussdb;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.sql.Blob;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.quartz.impl.jdbcjobstore.oracle.OracleDelegate;

public class GaussdbOracleDelegate extends OracleDelegate {

	@Override
	protected Object getObjectFromBlob(ResultSet rs, String colName)
			throws ClassNotFoundException, IOException, SQLException {
		Object obj = null;
		final InputStream binaryInput = rs.getBinaryStream(colName);
		if (binaryInput != null) {
			// 将二进制流转换为字节数组
			// byte[] bytes = binaryStream.readAllBytes(); // jdk9
			final byte[] bytes = toByteArray(binaryInput); // jdk8

			if (bytes.length < 1) {
				return null;
			}

			// 创建 ByteArrayInputStream
			final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
			final ObjectInputStream in = new ObjectInputStream(byteArrayInputStream);
			try {
				obj = in.readObject();
			} finally {
				in.close();
			}
		}

		return obj;
	}

	@Override
	protected Blob writeDataToBlob(ResultSet rs, int column, byte[] data) throws SQLException {
		final Blob blob = rs.getBlob(column);

		if (blob == null) {
			throw new SQLException("Driver's Blob representation is null!");
		}
//		logger.info(blob.getClass().getName());

		if (blob instanceof com.huawei.gaussdb.jdbc.core.types.PGBlob) { // is it an gaussdb blob?
			((com.huawei.gaussdb.jdbc.core.types.PGBlob) blob).setBytes(1, data);
			return blob;
		} else {
			throw new SQLException(
					"Driver's Blob representation is of an unsupported type: " + blob.getClass().getName());
		}
	}

	/**
	 * 将 InputStream 转换为字节数组.
	 *
	 * @param inputStream the input stream
	 * @return the byte[]
	 * @throws IOException Signals that an I/O exception has occurred.
	 */
	private static byte[] toByteArray(InputStream inputStream) throws IOException {
		final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
		int nRead;
		final byte[] data = new byte[1024];
		while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
			buffer.write(data, 0, nRead);
		}
		buffer.flush();
		return buffer.toByteArray();
	}
}

修改 quartz.properties,增加配置项

org.quartz.jobStore.driverDelegateClass: org.quartz.impl.jdbcjobstore.oracle.gaussdb.GaussdbOracleDelegate

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值