关于父子依赖关系的Spring批量项目编写器

时间:2017-06-01 06:26:10

标签: spring-batch

我无法使用我的子表(TBL_PAYMENT_DETAILS)添加Spring批处理的外键关系。

我收到此错误:Not-null property references a transient value在此行:paymentDetailsTblRepository.save(payDetails);

我试图通过调用两个作者来替换compositePaymentItemWriterpaymentRepoItemWriterpaymentInstallmentItemWriter认为paymentRepoItemWriter会先保留父作品,所以我可以将它引用到我的儿童表。但同样的问题。

我在想是否一定是因为我正在调用paymentDetailsTblRepository.save(payDetails)并且在StepJob完成之前父级尚未保留?

父表:

@Entity
@Table(name = "TBL_PAYMENT")
public class PaymentTbl {

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

    @Column(name = "BILL_PERIOD", nullable = false)
    private LocalDateTime billPeriod;

    @Column(name = "INVOICE_NO", nullable = false)
    private String invoiceNum;

    @Column(name = "AMOUNT")
    private BigDecimal amount;
}

子表:

@Entity
@Table(name = "TBL_PAYMENT_DETAILS")
public class PaymentDetailsTbl {

    @EmbeddedId
    private PaymentDetailsId id; // billPeriod and invoiceNum and paymentNum

    @Column(name = "INSTALLMENT_AMOUNT")
    private BigDecimal installmentAmount;

    @ManyToOne
    @JoinColumn(name = "PAY_ID", referencedColumnName = "ID",
            insertable = false, updatable = false)
    private PaymentTbl paymentTbl;

这是我的步骤:

// CalculatePaymentProcessor skips some rows (return null)
@Bean
protected Step calculatePaymentStep(
        @Autowired final CalculatePaymentReader calculatePaymentReader,
        @Autowired final CalculatePaymentProcessor calculatePaymentProcessor,
        @Autowired final RepositoryItemWriter<PaymentTbl> paymentRepoItemWriter,
        @Autowired final ItemWriter<PaymentTbl> paymentInstallmentItemWriter,
        @Autowired final CompositeItemWriter<PaymentTbl> compositePaymentItemWriter) throws Exception {

    return stepBuilderFactory.get("calculatePaymentStep")
            .allowStartIfComplete(true)
            .chunk(20000)
            .reader(calculatePaymentReader)
            .processor(calculatePaymentProcessor)
            //.writer(compositePaymentItemWriter)
            .writer(paymentRepoItemWriter)
            .writer(paymentInstallmentItemWriter)
            .build();
}

我的作家:

@Bean
public RepositoryItemWriter<PaymentTbl> paymentRepoItemWriter() throws Exception {
    RepositoryItemWriter<PaymentTbl> writer = new RepositoryItemWriter<>();
    writer.setMethodName("save");
    writer.setRepository(paymentTblRepository);
    writer.afterPropertiesSet();
    return writer;
}

@Bean
public ItemWriter<PaymentTbl> paymentInstallmentItemWriter() {
    return payList -> {

        for (PaymentTbl p : payList) {
            if (...) {
                IntStream.range(1, 4).forEach(num -> {
                    PaymentDetailsTbl payDetails = new PaymentDetailsTbl();
                    payDetails.setInstallmentAmount(...);
                    payDetails.setId(new PaymentDetailsId(...);
                    payDetails.setPaymentTbl(p);
                    paymentDetailsTblRepository.save(payDetails);
                });
            }
        }
    };
}

@Bean
public CompositeItemWriter<PaymentTbl> compositePaymentItemWriter() throws Exception {
    CompositeItemWriter<PaymentTbl> writer = new CompositeItemWriter();
    writer.setDelegates(Arrays.asList(paymentRepoItemWriter(), paymentInstallmentItemWriter()));
    return writer;
}

1 个答案:

答案 0 :(得分:0)

您多次致电writer(ItemWriter writer)。每一个都将替换以前的而不是添加到编写器列表中。相反,您需要创建一个列出您的委托的单CompositeItemWriter,然后只使用步骤构建器将复合编写器注册为您唯一的编写者。

@Bean
protected Step calculatePaymentStep(
        @Autowired final CalculatePaymentReader calculatePaymentReader,
        @Autowired final CalculatePaymentProcessor calculatePaymentProcessor,
        @Autowired final ItemWriter<PaymentTbl> compositeItemWriter
) throws Exception {

    return stepBuilderFactory.get("calculatePaymentStep")
            .allowStartIfComplete(true)
            .chunk(20000)
            .reader(calculatePaymentReader)
            .processor(calculatePaymentProcessor)
            .writer(compositeItemWriter)
            .build();
}

@Bean
protected ItemWriter<PaymentTbl> compositeItemWriter(
        @Autowired final RepositoryItemWriter<PaymentTbl> paymentRepoItemWriter,
        @Autowired final ItemWriter<PaymentTbl> paymentInstallmentItemWriter) {

    CompositeItemWriter<PaymentTbl> writer = new CompositeItemWriter<>();
    List<ItemWriter> delegates = new ArrayList<>();
    // make sure parent writer comes before child writer
    deleages.add(paymentRepoItemWriter);
    deleages.add(paymentInstallmentItemWriter);
    writer.setDelegates(delegates);
    return writer;
}