无法使用Spring Batch + Spring数据在数据库中插入行

时间:2019-06-07 12:14:58

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

我正在使用数据库表中没有键的旧式数据库。对于Java Sake,我必须使用Id注释。我的目标是从.dat文件读取数据并将其插入表中。我正在将spring batch用于上述目的。为了提高性能,使用了线程。但是我遇到无法解决的插入/更新问题。我引用了许多资料,但似乎没有一个能解决我的目的。请提供一些适当的解决方案或参考,以帮助我。预先感谢...

Entity.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

}

EmbeddedClass.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);     
    }

}

ErrorLog

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 个答案:

答案 0 :(得分:0)

实际上,该问题是由于在持久性上下文中发现重复而导致的,通过将块大小设置为1可以解决此重复。