bean类FlatFileItemReader的无效属性“id”,文件读取和使用的实体具有id

时间:2017-03-16 03:35:16

标签: spring hibernate jpa spring-data spring-batch

我正在研究一个读取csv文件的批处理程序,然后使用hibernate插入数据,我相信JPA。

我遇到的错误如下:

org.springframework.beans.NotReadablePropertyException: Invalid property 'id' of bean class [org.springframework.batch.item.file.FlatFileItemReader]: Could not find field for property during fallback access!

我已尝试以下方法解决此问题:

  • 读取没有名为id的列的文件时出现错误。仅尝试具有id的文件。同样的问题仍然存在
  • 在这里发现该问题可能缺少一个id字段(在SO线程上找到),因此为实体类中的id字段添加了以下getter和setter。

    @Id @Column(name =“id”,nullable = false) private Long id;

以及没有id的文件

@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.SEQUENCE) 
private Long id;

但发生了同样的问题。

getter和setter的结构如此。

public Long getId() { return id; }

public void setId(final Long id) { this.id = id; }
  • 这里建议使用Long而不是int(他们原来是什么)的另一个线程是原因。结果证明是。
  • 在调试器中发生问题的代码引用了此代码,即保存方法

    公共接口LCBOInventoryRepository扩展了CrudRepository {

    @Override
    @SuppressWarnings("unchecked")
    public LCBOInventory save(LCBOInventory lcboInventoryObject);
    

但是传递给该方法的每个对象都应该具有前面提到的Id信息。

根据要求,以下是用于此问题发生过程的读写器代码。

阅读器:

@Component
public class LCBOInventoryReader extends AbstractLCBOReader implements ItemReader, InterstepDataRetriever {

    @Autowired
    public LCBOInventoryReader(final String currentCSVFilePathKey ) {
        this.currentCSVFilePathKey = currentCSVFilePathKey;
    }

    private static final Logger log = LoggerFactory.getLogger(LCBOInventoryReader.class);

    @Override
    public ItemReader<LCBOInventory> read() throws UnexpectedInputException, ParseException, NonTransientResourceException {
        Class<LCBOInventory> classType = LCBOInventory.class;

        return createCSVReader(classType, currentCSVFilePath, inventoryTrackerProperties.getLCBOFilPropertiess().getInventory());
    }

    @Override
    public void retrieveInterstepDataFromJobContext(final ExecutionContext jobContext) {
        this.currentCSVFilePath = (String) jobContext.get(currentCSVFilePathKey);
    }
}

这是扩展的Abstract类:

public abstract class AbstractLCBOReader {

    @Autowired
    protected LCBOInventoryTrackerProperties inventoryTrackerProperties;

    protected String currentCSVFilePathKey;
    protected String currentCSVFilePath;

    private static final Logger log = LoggerFactory.getLogger(AbstractLCBOReader.class);

    protected <T> ItemReader<T> createCSVReader(final Class<T> classType,
                                                 final String currentCSVFilePath,
                                                 final LCBOFileDetailsProperties properties) {

        FlatFileItemReader<T> reader = new FlatFileItemReader<>();
        // Skip a line to ignore the header information in these files
        reader.setLinesToSkip(properties.getNumberOfLinesToSkipInFile());
        reader.setResource(new FileSystemResource(currentCSVFilePath + File.separator + properties.getFileName()));
        reader.setLineMapper(createLineMapper(classType, properties));
        reader.setRecordSeparatorPolicy(new DefaultRecordSeparatorPolicy());
        reader.setEncoding("utf8");

        return reader;
    }

    private <T> LineMapper<T> createLineMapper(final Class<T> classType, final LCBOFileProperties.LCBOFileDetailsProperties properties) {
        DefaultLineMapper<T> lineMapper = new DefaultLineMapper<>();
        lineMapper.setLineTokenizer(createLineTokenizer(properties));
        lineMapper.setFieldSetMapper(createFieldSetMapper(classType));

        return lineMapper;
    }

    private <T> FieldSetMapper<T> createFieldSetMapper(final Class<T> classType) {
        BeanWrapperFieldSetMapper<T> fieldSetMapper = new BeanWrapperFieldSetMapper<>();
        fieldSetMapper.setTargetType(classType);

        return fieldSetMapper;
    }

    private LineTokenizer createLineTokenizer(final LCBOFileProperties.LCBOFileDetailsProperties properties) {
        LCBOFileProperties.Column[] columns = properties.getColumns();
        int[] columnIndexes = new int[columns.length];
        String[] columnNames = new String[columns.length];

        // populating the columnIndexes
        for (int i = 0; i < columns.length; i++) {
            columnIndexes[i] = columns[i].getColumnIndex();
            columnNames[i] = columns[i].getColumnName();
        }

        DelimitedLineTokenizer lineTokenizer = new DelimitedLineTokenizer();
        lineTokenizer.setIncludedFields(columnIndexes);
        lineTokenizer.setNames(columnNames);
        lineTokenizer.setDelimiter(",");
        lineTokenizer.setQuoteCharacter('"');

        return lineTokenizer;
    }
}

读者实现的界面InterstepDataRetriever

public interface InterstepDataRetriever {

    @BeforeStep
    default void retrieveValuesFromStepContext(StepExecution stepExecution) {
        JobExecution jobExecution = stepExecution.getJobExecution();
        ExecutionContext jobContext = jobExecution.getExecutionContext();
        retrieveInterstepDataFromJobContext(jobContext);
    }

    void retrieveInterstepDataFromJobContext(ExecutionContext jobContext);
}

后者不应对此问题产生任何影响,但为了完整性而包括在内(除了你永远不知道)。

<德尔>作家(旧):

@Component
public class LCBOInventoryWriter implements ItemWriter<LCBOInventory> {

    @Autowired
    private LCBOInventoryRepository inventoryDAO;

    @Override
    public void write(List<? extends LCBOInventory> lcboInventoryItem) throws Exception {
        inventoryDAO.save(lcboInventoryItem);
    }
}

Writer(新增 - 这与步骤放在同一个文件中):

@Bean
public ItemWriter<LCBOStore> writer() {
    HibernateItemWriter writer = new HibernateItemWriter();
    writer.setSessionFactory(sessionFactory);
    System.out.println("writing stuff");
    return writer;
}

这是执行代码时的堆栈跟踪(编辑:堆栈跟踪已更新):

org.hibernate.MappingException: Unknown entity: org.springframework.batch.item.file.FlatFileItemReader
    at org.hibernate.internal.SessionFactoryImpl.getEntityPersister(SessionFactoryImpl.java:783) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.internal.SessionImpl.getEntityPersister(SessionImpl.java:1520) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.engine.internal.ForeignKeys.isTransient(ForeignKeys.java:225) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.event.internal.AbstractSaveEventListener.getEntityState(AbstractSaveEventListener.java:510) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:83) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:73) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.internal.SessionImpl.fireSaveOrUpdate(SessionImpl.java:648) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:640) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:635) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.springframework.batch.item.database.HibernateItemWriter.doWrite(HibernateItemWriter.java:140) ~[spring-batch-infrastructure-3.0.7.RELEASE.jar:3.0.7.RELEASE]
    at org.springframework.batch.item.database.HibernateItemWriter.write(HibernateItemWriter.java:113) ~[spring-batch-infrastructure-3.0.7.RELEASE.jar:3.0.7.RELEASE]
    at org.springframework.batch.core.step.item.SimpleChunkProcessor.writeItems(SimpleChunkProcessor.java:175) ~[spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
    at org.springframework.batch.core.step.item.SimpleChunkProcessor.doWrite(SimpleChunkProcessor.java:151) ~[spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
    at org.springframework.batch.core.step.item.SimpleChunkProcessor.write(SimpleChunkProcessor.java:274) ~[spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
    at org.springframework.batch.core.step.item.SimpleChunkProcessor.process(SimpleChunkProcessor.java:199) ~[spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
    at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:75) ~[spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
    at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:406) ~[spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
    at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:330) ~[spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
    at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133) ~[spring-tx-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:271) ~[spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
    at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:81) ~[spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
    at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:374) ~[spring-batch-infrastructure-3.0.7.RELEASE.jar:3.0.7.RELEASE]
    at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215) ~[spring-batch-infrastructure-3.0.7.RELEASE.jar:3.0.7.RELEASE]
    at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:144) ~[spring-batch-infrastructure-3.0.7.RELEASE.jar:3.0.7.RELEASE]
    at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:257) ~[spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
    at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:200) ~[spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
    at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:148) [spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
    at org.springframework.batch.core.job.AbstractJob.handleStep(AbstractJob.java:392) [spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
    at org.springframework.batch.core.job.SimpleJob.doExecute(SimpleJob.java:135) [spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
    at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:306) [spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
    at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:135) [spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
    at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50) [spring-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:128) [spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_92]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_92]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_92]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_92]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333) [spring-aop-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) [spring-aop-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) [spring-aop-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:127) [spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) [spring-aop-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) [spring-aop-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at com.sun.proxy.$Proxy54.run(Unknown Source) [na:na]
    at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.execute(JobLauncherCommandLineRunner.java:214) [spring-boot-autoconfigure-1.5.1.RELEASE.jar:1.5.1.RELEASE]
    at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.executeLocalJobs(JobLauncherCommandLineRunner.java:231) [spring-boot-autoconfigure-1.5.1.RELEASE.jar:1.5.1.RELEASE]
    at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.launchJobFromProperties(JobLauncherCommandLineRunner.java:123) [spring-boot-autoconfigure-1.5.1.RELEASE.jar:1.5.1.RELEASE]
    at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.run(JobLauncherCommandLineRunner.java:117) [spring-boot-autoconfigure-1.5.1.RELEASE.jar:1.5.1.RELEASE]
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:776) [spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
    at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:760) [spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
    at org.springframework.boot.SpringApplication.afterRefresh(SpringApplication.java:747) [spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) [spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1162) [spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1151) [spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
    at com.lcbo.config.LCBOBatchConfig.main(LCBOBatchConfig.java:173) [classes/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_92]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_92]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_92]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_92]
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147) [idea_rt.jar:na]

所以简而言之,我不知道它需要工作的id字段,为什么它认为它是一个实体(没有@Entity注释),以及我如何能够满足它所需要的,或者修复它这样就不需要了。

1 个答案:

答案 0 :(得分:0)

您确定自己正确地将requests传递给了Class<T> classType吗?

此错误使您看起来好像是在BeanWrapperFieldSetMapper班而不是FlatFileItemReader

  

NotReadablePropertyException:无效的属性&#39; id&#39;豆类   [org.springframework.batch.item.file的 FlatFileItemReader ]:

更新:请检查作者的LCBOInventory方法。堆栈跟踪显示错误来自那里,而不是来自您的读者。你是否有可能试图坚持write对象?

  

LCBOInventoryWriter.write(LCBOInventoryWriter.java:19)