Using Redshfit as Spring batch Job Repository and alternatives to SEQUENCE in Redshfit

前端 未结 1 632
温柔的废话
温柔的废话 2021-01-21 17:19

One of the requirements in my project is to place the spring batch schema on amazon redshift db.
I am planning to start from the schema-postgresql.sql as the base line as re

相关标签:
1条回答
  • 2021-01-21 17:28

    Here's how I got at least that part to (apparently) work:

    In my subclass of DefaultBatchConfigurer, I added this code:

    @Override
    protected JobRepository createJobRepository() throws Exception
    {
        JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
        factory.setDataSource(dataSource);
        factory.setTransactionManager(getTransactionManager());
        factory.setIncrementerFactory(new RedshiftIncrementerFactory(dataSource));
        factory.afterPropertiesSet();
        return factory.getObject();
    }
    

    The factory object looks like

    public class RedshiftIncrementerFactory implements DataFieldMaxValueIncrementerFactory
    {
        private DataSource dataSource;
    
        public RedshiftIncrementerFactory(DataSource ds)
        {
            this.dataSource = ds;
        }
    
        @Override
        public DataFieldMaxValueIncrementer getIncrementer(String databaseType, String incrementerName)
        {
            return new RedshiftIncrementer(dataSource, incrementerName);
        }
    
        @Override
        public boolean isSupportedIncrementerType(String databaseType)
        {
            return POSTGRES.toString().equals(databaseType);
        }
    
        @Override
        public String[] getSupportedIncrementerTypes()
        {
            return new String[]{POSTGRES.toString()};
        }
    
    }
    

    And then, finally, the incrementer itself:

    public class RedshiftIncrementer extends AbstractSequenceMaxValueIncrementer
    {
        public RedshiftIncrementer(DataSource dataSource, String incrementorName)
        {
            super(dataSource, incrementorName);
        }
    
        // I need to run two queries here, since Redshift doesn't support sequences
        @Override
        protected long getNextKey() throws DataAccessException {
            Connection con = DataSourceUtils.getConnection(getDataSource());
            Statement stmt = null;
            ResultSet rs = null;
            try {
                stmt = con.createStatement();
                DataSourceUtils.applyTransactionTimeout(stmt, getDataSource());
                String table = getIncrementerName();
                stmt.executeUpdate("UPDATE " + table + " SET ID = ID + 1");
                rs = stmt.executeQuery("SELECT ID FROM " + table + " WHERE UNIQUE_KEY='0'");
                if (rs.next()) {
                    return rs.getLong(1);
                }
                else {
                    throw new DataAccessResourceFailureException("Sequence query did not return a result");
                }
            }
            catch (SQLException ex) {
                throw new DataAccessResourceFailureException("Could not obtain sequence value", ex);
            }
            finally {
                JdbcUtils.closeResultSet(rs);
                JdbcUtils.closeStatement(stmt);
                DataSourceUtils.releaseConnection(con, getDataSource());
            }
        }
    
        @Override
        protected String getSequenceQuery()
        {
            // No longer used
            return null;
        }
    }
    

    This at least allows the job to start. However, there are other problems with Redshift that I will detail elsewhere.

    0 讨论(0)
提交回复
热议问题