spring-boot - 无法使用 Spring Batch + Spring 数据在数据库中插入行
问题描述
我正在使用其中 db 表没有键的旧数据库。对于 java Sake,我必须使用 Id 注释。我的目标是从 .dat 文件中读取数据并将其插入表中。我正在为上述目的使用弹簧批次。为了提高性能,使用了线程。但是我遇到了我无法弄清楚的插入/更新问题。我参考了许多来源,但似乎没有一个能解决我的目的。请通过提供一些适当的解决方案或参考来帮助我。提前致谢...
实体.java
@Entity
@Table(name = "int_repl_mkt_val")
public class IntReplMktVal implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
private IntReplMktValId id;
@Column(name = "acct_sys_cd")
private String acctSysCd;
@Column(name = "co_num", nullable = false)
private Integer coNum;
@Column(name = "last_mod_tmstmp")
@Temporal(TemporalType.TIMESTAMP)
private Date lastModTmstmp;
@Column(name = "pim_owned", nullable = false)
private String pimOwned;
@Column(name = "position", nullable = false)
private BigDecimal position;
@Column(name = "pricing_plan")
private String pricingPlan;
@Column(name="source_system",nullable=false)
private String sourceSystem;
... getter and setter
}
嵌入式类.java
@Embeddable
public class IntReplMktValId implements Serializable
{
private static final long serialVersionUID = 4824041485763129937L;
@Column(name = "acct_id",nullable=false)
private Integer acctId;
@Column(name = "asset_id",nullable=false)
private Integer assetId;
... getter and setter
}
jpaRepository.class
@Repository
public interface IntReplMktValRepository extends JpaRepository<IntReplMktVal, IntReplMktValId>
{
}
BatchConfiguration.class
@Configuration
public class IMAPPositionBatchConfiguration
{
@Autowired
JobBuilderFactory jobBuilderFactory;
@Autowired
StepBuilderFactory stepBuilderFactory;
@StepScope
@Bean(name="imapPositionReader")
public FlatFileItemReader<IMAPPositionInputMapperDTO> reader(@Value("#{jobParameters['fileName']}") String fileName) throws IOException
{
FlatFileItemReader<IMAPPositionInputMapperDTO> newBean = new FlatFileItemReader<>();
newBean.setName("fileReader");
newBean.setResource(new InputStreamResource(FileUtils.openInputStream(new File(fileName))));
newBean.setLineMapper(this.lineMapper());
newBean.setLinesToSkip(1);
return newBean;
}
public DefaultLineMapper<IMAPPositionInputMapperDTO> lineMapper()
{
DefaultLineMapper<IMAPPositionInputMapperDTO> lineMapper = new DefaultLineMapper<>();
lineMapper.setLineTokenizer(this.lineTokenizer());
IMAPPositionReader imapPositionReader = new IMAPPositionReader();
lineMapper.setFieldSetMapper(imapPositionReader);
return lineMapper;
}
public DelimitedLineTokenizer lineTokenizer()
{
DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer();
tokenizer.setDelimiter("|");
tokenizer.setNames("field1","field2","field3");
tokenizer.setIncludedFields(5,4,7);
return tokenizer;
}
public ItemProcessor<IMAPPositionInputMapperDTO, IntReplMktVal> processor()
{
return new IMAPPositionProcessor();
}
@Bean(name="imapPositionBatchWriter")
public ItemWriter<IntReplMktVal> writer()
{
return new IMAPPositionWriter();
}
@Bean(name="imapPositionListener")
public JobExecutionListenerSupport jobCompletionListener()
{
return new IMAPPositionJobListener();
}
@Bean(name="imapPositionTaskExecutor")
public ThreadPoolTaskExecutor taskExecutor()
{
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(50);
executor.setMaxPoolSize(100);
return executor;
}
@Bean(name="imapPositionStep")
public Step step(@Autowired @Qualifier("imapPositionTaskExecutor")TaskExecutor taskExecutor) throws IOException
{
return stepBuilderFactory.get("imapPositionStep")
.<IMAPPositionInputMapperDTO, IntReplMktVal>chunk(100)
.reader(this.reader(null))
.processor(this.processor())
.writer(this.writer())
.taskExecutor(taskExecutor)
.build();
}
@Bean(name="imapPositionFileImportJob")
public Job importUserJob(@Autowired @Qualifier("imapPositionStep") Step step)
{
return jobBuilderFactory
.get("imapPositionFileImportJob"+new Date())
.incrementer(new RunIdIncrementer())
.listener(this.jobCompletionListener())
.flow(step)
.end()
.build();
}
}
BatchWriter.java
public class IMAPPositionWriter implements ItemWriter<IntReplMktVal>
{
@Autowired
IntReplMktValRepository intReplMktValRepository;
@Override
public void write(List<? extends IntReplMktVal> items) throws Exception
{
intReplMktValRepository.saveAll(items);
}
}
错误日志
2019-06-07 17:22:01,522 ERROR [scopedTarget.imapPositionTaskExecutor-4] org.hibernate.internal.ExceptionMapperStandardImpl : HHH000346: Error during managed flush [org.hibernate.HibernateException: Duplicate identifier in table for: [com.capgroup.horizon.pricecapture.entities.IntReplMktVal#component[acctId,assetId]{assetId=274800, acctId=1}]]
注意:无论重复或任何其他问题,我都必须将所有数据插入表中,因为未定义键,因此每个数据都是有效的。
解决方案
实际上问题是由于在持久上下文中发现的重复,通过将块大小设置为 1 来解决。
推荐阅读
- google-cloud-platform - 是否可以在不使用 BigQuery 清理的情况下查询存储在云存储中的日志数据?
- api - 尝试进行身份验证时如何解决“无法创建房间”?
- java - 如何使用多部分/表单数据?
- c# - 是否可以使用自定义 ComboBox 填充 DataGridViewComboBoxCell?
- python-3.x - 我正在尝试在 matplotlib 中将 x 轴从底部移动到顶部。但是 xaxis.set_ticks_position('top') 似乎不能正常工作?
- android - 将数据从 page1 发送到 page2 并保存
- shinydashboard - R包创建:如何自动安装丢失的包?
- gitahead - 如何设置SSH识别文件路径
- bash - 在带反引号的 AWK 表达式中包含命令行参数
- java - 休眠:启用 useAffectedRows 会导致无操作更新的 OptimisticLockExceptions