【发布时间】:2017-08-07 01:58:07
【问题描述】:
我目前正在开发一个读取 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 线程上找到),因此为 Entity 类中的 id 字段添加了 getter 和 setter。
@Id @Column(name = "id", nullable = false) 私有长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(它们最初是什么)是原因。原来是这样。
-
调试器中出现问题的代码引用了这段代码,即save方法
公共接口 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);
}
}
这是扩展的抽象类:
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(New - 这与 Step 放在同一个文件中):
@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 注释),以及我如何才能满足它的需求,或者修复这样就不需要了。
【问题讨论】:
-
对于说应该关闭的人,可以发布为什么要改进问题吗?
-
可以分享一下你的读写器的配置吗?
-
@MichaelMinella 当然。我已经用添加的这些文件更新了问题。
-
你能提供更多的堆栈跟踪吗?
-
@MichaelMinella 确定。请查看最新编辑
标签: spring hibernate jpa spring-data spring-batch