【问题标题】:Spring Batch rowMapper: no matching editors or conversion strategy foundSpring Batch rowMapper:找不到匹配的编辑器或转换策略
【发布时间】:2018-01-06 06:44:35
【问题描述】:

我正在尝试运行我的第一个 Batch Spring 应用程序,但我在运行时遇到了行映射器的以下问题:

无法将 [com.turef.batch.ProductMapper] 类型的值转换为 属性所需的类型 [org.springframework.jdbc.core.RowMapper] 'rowMapper': 没有找到匹配的编辑器或转换策略

程序必须将一些数据从我的 sql 导出到平面文件 (csv)。下面我包括主要文件(如果需要,我可以添加任何文件)。我也关心 pom.xml 中的版本。

我的 IDE 是 Eclipse。这是我的 pom.xml :

<project xmlns="http://maven.apache.org/POM/4.0.0" 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0         http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.tutoref</groupId>
  <artifactId>spring-batch-example</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>spring-batch-example</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <!-- Spring core -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>4.3.10.RELEASE</version>
    </dependency>
    <!-- Spring batch core -->
    <dependency>
        <groupId>org.springframework.batch</groupId>
        <artifactId>spring-batch-core</artifactId>
        <version>3.0.8.RELEASE</version>
    </dependency>
    <!-- MySQL connector -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>6.0.6</version>
    </dependency>
    <!-- Spring jdbc -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>4.3.10.RELEASE</version>
    </dependency>
    <!-- The JAXB Api -->
    <dependency>
        <groupId>javax.xml.bind</groupId>
        <artifactId>jaxb-api</artifactId>
        <version>2.2.6</version>
    </dependency>
    <!-- Junit for unit testing -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

我的工作定义 xml:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:batch="http://www.springframework.org/schema/batch"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/batch
        http://www.springframework.org/schema/batch/spring-batch-2.2.xsd
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
    ">

    <import resource="spring-context.xml" />
    <import resource="datasource.xml" />

    <bean id="product" class="com.tutoref.batch.entity.Product" scope="prototype" />
    <bean id="itemProcessor" class="com.tutoref.batch.ProductItemProcessor" />
    <bean id="jobListener" class="com.tutoref.batch.ProductJobListener" />


    <!-- Reading from the database and returning a mapper row -->
    <bean id="productItemReader"
        class="org.springframework.batch.item.database.JdbcCursorItemReader">
        <property name="dataSource" ref="productDataSource" />
        <property name="sql" value="SELECT * FROM products" />
        <property name="rowMapper">
            <bean class="com.tutoref.batch.ProductMapper" />
        </property>

    </bean>

    <!-- Writing a line into an output flat file -->
    <bean id="productFlatFileItemWriter" class="org.springframework.batch.item.file.FlatFileItemWriter" scope="step">
        <property name="resource" value="file:csv/products.csv" />
        <!-- Converting a product object into delimited list of strings -->
        <property name="lineAggregator">
            <bean class="org.springframework.batch.item.file.transform.DelimitedLineAggregator">
                <property name="delimiter" value="|" />
                <property name="fieldExtractor">
                    <!-- Returning the value of beans property using reflection -->
                    <bean class="org.springframework.batch.item.file.transform.BeanWrapperFieldExtractor">
                        <property name="names" value="name,unitPrice,quantity" />
                    </bean>
                </property>
            </bean>
        </property>
    </bean>

    <!-- And finally ... the job definition -->
    <batch:job id="productJob">
        <batch:step id="step1">
            <batch:tasklet transaction-manager="transactionManager">
                <batch:chunk reader="productItemReader" writer="productFlatFileItemWriter"
                    processor="itemProcessor" commit-interval="10" />
            </batch:tasklet>
        </batch:step>
        <batch:listeners>
            <batch:listener ref="jobListener" />
        </batch:listeners>
    </batch:job>
</beans>

行映射器代码:

public class ProductMapper implements FieldSetMapper<Product> {

    @Override
    public Product mapFieldSet(FieldSet fieldSet) throws BindException {
        Product product = new Product();
        product.setId(fieldSet.readInt(0));
        product.setName(fieldSet.readString(1));
        product.setQuantity(fieldSet.readInt(2));
        product.setUnitPrice(fieldSet.readDouble(3));
        return product;
    }


}

还有主课:

public class App 
{
    public static void main(String[] args){

        ApplicationContext context = new ClassPathXmlApplicationContext("job-products.xml");

        JobLauncher jobLauncher = (JobLauncher) context.getBean("jobLauncher");
        Job job = (Job) context.getBean("productJob");

        try {
            JobExecution execution = jobLauncher.run(job, new JobParameters());
            System.out.println("Job Exit Status : "+ execution.getStatus());

        } catch (JobExecutionException e) {
            System.out.println("The Job has failed :" + e.getMessage());
            e.printStackTrace();
        }

    }
}

异常的堆栈跟踪:

INFO: 未设置 TaskExecutor,默认为同步 执行人。加载类com.mysql.jdbc.Driver'. This is deprecated. The new driver class iscom.mysql.cj.jdbc.Driver'。司机是 通过 SPI 自动注册并手动加载驱动程序 类通常是不必要的。 2017 年 7 月 30 日下午 2:09:59 org.springframework.jdbc.datasource.DriverManagerDataSource setDriverClassName INFO:加载的 JDBC 驱动程序:com.mysql.jdbc.Driver 线程“主”中的异常 org.springframework.beans.factory.BeanCreationException:错误 创建在类路径中定义的名称为“productItemReader”的 bean 资源 [job-products.xml]:bean 初始化失败;嵌套的 例外是 org.springframework.beans.ConversionNotSupportedException:失败 将“com.turef.batch.ProductMapper”类型的属性值转换为 属性所需的类型“org.springframework.jdbc.core.RowMapper” '行映射器';嵌套异常是 java.lang.IllegalStateException: 无法将 [com.turef.batch.ProductMapper] 类型的值转换为 属性所需的类型 [org.springframework.jdbc.core.RowMapper] 'rowMapper':没有找到匹配的编辑器或转换策略 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:547) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475) 在 org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304) 在 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228) 在 org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300) 在 org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195) 在 org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:703) 在 org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760) 在 org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482) 在 org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:139) 在 org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:83) 在 com.turef.batch.App.main(App.java:19) 引起: org.springframework.beans.ConversionNotSupportedException:失败 将“com.turef.batch.ProductMapper”类型的属性值转换为 属性所需的类型“org.springframework.jdbc.core.RowMapper” '行映射器';嵌套异常是 java.lang.IllegalStateException: 无法将 [com.turef.batch.ProductMapper] 类型的值转换为 属性所需的类型 [org.springframework.jdbc.core.RowMapper] 'rowMapper':没有找到匹配的编辑器或转换策略 org.springframework.beans.BeanWrapperImpl.convertIfNecessary(BeanWrapperImpl.java:474) 在 org.springframework.beans.BeanWrapperImpl.convertForProperty(BeanWrapperImpl.java:511) 在 org.springframework.beans.BeanWrapperImpl.convertForProperty(BeanWrapperImpl.java:505) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.convertForProperty(AbstractAutowireCapableBeanFactory.java:1502) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1461) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1197) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537) ... 11 更多原因:java.lang.IllegalStateException:不能 将 [com.turef.batch.ProductMapper] 类型的值转换为必需 为属性键入 [org.springframework.jdbc.core.RowMapper] 'rowMapper':没有找到匹配的编辑器或转换策略 org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:267) 在 org.springframework.beans.BeanWrapperImpl.convertIfNecessary(BeanWrapperImpl.java:459) ... 17 更多

谢谢

【问题讨论】:

    标签: java spring-batch


    【解决方案1】:

    无法将类型 [com.turef.batch.ProductMapper] 的值转换为属性“rowMapper”所需的类型 [org.springframework.jdbc.core.RowMapper]:找不到匹配的编辑器或转换策略

    这个异常意味着productItemReader bean 正在等待rowmapper 属性中的org.springframework.jdbc.core.RowMapper 对象,但它正在接收com.tutoref.batch.ProductMapper 类型的引用对象。

    问题出在public class ProductMapper implements FieldSetMapper&lt;Product&gt;

    转到 ProductMapper 类并实现 org.springframework.jdbc.core.RowMapper 而不是 FieldSetMapper

    这是一个如何实现 RowMapper 接口的示例,MessageContainer 是一个 pojo 示例,例如您项目中的Product 类。

    public class MessageContainerMapper implements RowMapper<MessageContainer> {
    
        @Override
        public MessageContainer mapRow(ResultSet rs, int rowNum) throws SQLException {
            MessageContainer mc = new MessageContainer();
            mc.setId(rs.getInt("id"));
            mc.setName(rs.getString("name"));
            return mc;
        }
    
    }
    

    【讨论】:

    • 确实有道理。您的修复解决了它现在 5/5 工作的问题。非常感谢。
    猜你喜欢
    • 2011-09-21
    • 1970-01-01
    • 2014-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多