【问题标题】:Spring Batch: Repository changes not committingSpring Batch:存储库更改未提交
【发布时间】:2017-05-08 14:49:57
【问题描述】:

我在使用 RepositoryItemReader、自定义处理器和 RepositoryItemWriter 将所有更改保存回数据库中的 spring 批处理配置时遇到了问题。我用谷歌搜索了我的手,并不能真正找到答案或看到问题出在哪里:(

我的工作定义是:

@NonNull
@Autowired
private MailRepository repository; //data jpa with hibernate and mssql

@Bean
Job sendMailJob(JobExecutionListener jobCompletionListener) { 
    return getJobBuilderFactory().get("sendMailJob")
            .incrementer(new TimeStampIncrementer())
            .listener(jobCompletionListener)
            .flow(sendMailStep1())
            .end()
            .build();
}

@Bean
Step sendMailStep1() {
    return getStepBuilderFactory()
            .get("sendMailStep1").allowStartIfComplete(true)
            .<Mail, Mail> chunk(MAIL_MAX_COUNT)
            .reader(mailReader())
            .processor(sendMailProcessor())
            .writer(mailWriter())
            .build();
}

@Bean
ItemReader<Mail> mailReader() {
    RepositoryItemReader<Mail> reader = new RepositoryItemReader<>();
    reader.setRepository(getRepository());
    reader.setPageSize(MAIL_MAX_COUNT);
    reader.setMaxItemCount(MAIL_MAX_COUNT);
    reader.setMethodName(MailRepository.SEND_BATCH_METHOD_NAME);
    reader.setArguments(Arrays.asList(MailStatus.OPEN));

    Map<String, Direction> sorting = new HashMap<>();
    sorting.put("created", Direction.DESC);
    reader.setSort(sorting);

    return reader;
}

@Bean
ItemProcessor<Mail ,Mail> sendMailProcessor() {
    return new ItemProcessor<Mail, Mail>() {
        @Override
        public Mail process(Mail mail) throws Exception {
            try {
                sendMail(mail);
                mail.setSent();
            } catch (Exception e) {
                mail.setFailed();
            }
            return mail;
        }
    };
}

@Bean
ItemWriter<Mail> mailWriter() {
    RepositoryItemWriter<Mail> writer = new RepositoryItemWriter<>();
    writer.setRepository(getRepository());
    writer.setMethodName("save");
    return writer;
}

这段代码并没有什么特别之处:状态为“OPEN”的邮件将被读取,并由处理器发送,这也会更改状态,并且这些更改应由作者使用 save 写回存储库。

当我调试时,读取、发送和更改状态(不在数据库中)工作正常,但是在编写器调用保存后,所有这些更改都不会保留在数据库中。使用的 PlatformTransactionManager 似乎很好,指向正确的 DataSource 并使用正确的 TransactionMode。在批处理存储库(相同的数据库)内部进行的所有更改都将正确写入,但我在邮件实体中没有任何更改。 我在其他仅读取和删除过期实体的批次中也遇到了这些问题。阅读工作正常,但没有实体被删除。因此,似乎该事务被未提交的存储库使用。也不例外; @EnableBatchProcessing 在应用程序类中设置。

有没有人遇到过同样的问题或者可以帮帮我?

感谢您的建议! 丹尼斯

调试输出:

o.s.batch.repeat.support.RepeatTemplate  : Repeat operation about to start at count=1
o.s.b.item.data.RepositoryItemReader     : Reading page 0
o.s.orm.jpa.EntityManagerFactoryUtils    : Opening JPA EntityManager
o.s.orm.jpa.EntityManagerFactoryUtils    : Registering transaction synchronization for JPA EntityManager
o.h.jpa.criteria.CriteriaQueryImpl       : Rendered criteria query -> select count(generatedAlias0) from Mail as generatedAlias0 where generatedAlias0.status=:param0
org.hibernate.SQL                        : select count(mail0_.id) as col_0_0_ from mail mail0_ where mail0_.status=?
Hibernate: select count(mail0_.id) as col_0_0_ from mail mail0_ where mail0_.status=?
org.hibernate.loader.Loader              : Result set row: 0
org.hibernate.loader.Loader              : Result row: 
o.h.jpa.criteria.CriteriaQueryImpl       : Rendered criteria query -> select generatedAlias0 from Mail as generatedAlias0 where generatedAlias0.status=:param0 order by generatedAlias0.created desc
org.hibernate.SQL                        : select TOP(?) mail0_.id as id1_13_, mail0_.created as created2_13_, mail0_.last_modified as last_mod3_13_, mail0_.charset as charset4_13_, mail0_.sender as sender5_13_, mail0_.message as message6_13_, mail0_.sent as sent7_13_, mail0_.status as status8_13_, mail0_.subject as subject9_13_, mail0_.subtype as subtype10_13_, mail0_.suppress_failure as suppres11_13_ from mail mail0_ where mail0_.status=? order by mail0_.created desc
Hibernate: select TOP(?) mail0_.id as id1_13_, mail0_.created as created2_13_, mail0_.last_modified as last_mod3_13_, mail0_.charset as charset4_13_, mail0_.sender as sender5_13_, mail0_.message as message6_13_, mail0_.sent as sent7_13_, mail0_.status as status8_13_, mail0_.subject as subject9_13_, mail0_.subtype as subtype10_13_, mail0_.suppress_failure as suppres11_13_ from mail mail0_ where mail0_.status=? order by mail0_.created desc
org.hibernate.loader.Loader              : Result set row: 0
org.hibernate.loader.Loader              : Result row: EntityKey[com.some.package.mail.Mail#11]
o.h.engine.internal.TwoPhaseLoad         : Resolving associations for [com.some.package.mail.Mail#11]
o.h.engine.internal.TwoPhaseLoad         : Done materializing entity [com.some.package.mail.Mail#11]
o.s.batch.repeat.support.RepeatTemplate  : Repeat is complete according to policy and result value.
stractLoadPlanBasedCollectionInitializer : Loading collection: [com.some.package.mail.Mail.to#11]
org.hibernate.SQL                        : select to0_.mail_id as mail_id1_16_0_, to0_.mail_to as mail_to2_16_0_ from mail_to to0_ where to0_.mail_id=?
Hibernate: select to0_.mail_id as mail_id1_16_0_, to0_.mail_to as mail_to2_16_0_ from mail_to to0_ where to0_.mail_id=?
o.h.l.p.e.p.i.ResultSetProcessorImpl     : Preparing collection intializer : [com.some.package.mail.Mail.to#11]
o.h.e.l.internal.CollectionLoadContext   : 1 collections were found in result set for role: com.some.package.mail.Mail.to
o.h.e.l.internal.CollectionLoadContext   : Collection fully initialized: [com.some.package.mail.Mail.to#11]
o.h.e.l.internal.CollectionLoadContext   : 1 collections initialized for role: com.some.package.mail.Mail.to
o.h.r.j.i.ResourceRegistryStandardImpl   : HHH000387: ResultSet's statement was not registered
stractLoadPlanBasedCollectionInitializer : Done loading collection
stractLoadPlanBasedCollectionInitializer : Loading collection: [com.some.package.mail.Mail.cc#11]
org.hibernate.SQL                        : select cc0_.mail_id as mail_id1_15_0_, cc0_.cc as cc2_15_0_ from mail_cc cc0_ where cc0_.mail_id=?
Hibernate: select cc0_.mail_id as mail_id1_15_0_, cc0_.cc as cc2_15_0_ from mail_cc cc0_ where cc0_.mail_id=?
o.h.l.p.e.p.i.ResultSetProcessorImpl     : Preparing collection intializer : [com.some.package.mail.Mail.cc#11]
o.h.e.l.internal.CollectionLoadContext   : 1 collections were found in result set for role: com.some.package.mail.Mail.cc
o.h.e.l.internal.CollectionLoadContext   : Collection fully initialized: [com.some.package.mail.Mail.cc#11]
o.h.e.l.internal.CollectionLoadContext   : 1 collections initialized for role: com.some.package.mail.Mail.cc
o.h.r.j.i.ResourceRegistryStandardImpl   : HHH000387: ResultSet's statement was not registered
stractLoadPlanBasedCollectionInitializer : Done loading collection
stractLoadPlanBasedCollectionInitializer : Loading collection: [com.some.package.mail.Mail.bcc#11]
org.hibernate.SQL                        : select bcc0_.mail_id as mail_id1_14_0_, bcc0_.bcc as bcc2_14_0_ from mail_bcc bcc0_ where bcc0_.mail_id=?
Hibernate: select bcc0_.mail_id as mail_id1_14_0_, bcc0_.bcc as bcc2_14_0_ from mail_bcc bcc0_ where bcc0_.mail_id=?
o.h.l.p.e.p.i.ResultSetProcessorImpl     : Preparing collection intializer : [com.some.package.mail.Mail.bcc#11]
o.h.l.p.e.p.i.ResultSetProcessorImpl     : Starting ResultSet row #0
e.p.i.CollectionReferenceInitializerImpl : Found row of collection: [com.some.package.mail.Mail.bcc#11]
o.h.e.l.internal.CollectionLoadContext   : 1 collections were found in result set for role: com.some.package.mail.Mail.bcc
o.h.e.l.internal.CollectionLoadContext   : Collection fully initialized: [com.some.package.mail.Mail.bcc#11]
o.h.e.l.internal.CollectionLoadContext   : 1 collections initialized for role: com.some.package.mail.Mail.bcc
o.h.r.j.i.ResourceRegistryStandardImpl   : HHH000387: ResultSet's statement was not registered
stractLoadPlanBasedCollectionInitializer : Done loading collection
o.s.b.item.data.RepositoryItemWriter     : Writing to the repository with 1 items.
o.s.j.d.DataSourceTransactionManager     : Participating in existing transaction
o.s.b.c.step.item.ChunkOrientedTasklet   : Inputs not busy, ended: false
o.s.batch.core.step.tasklet.TaskletStep  : Applying contribution: [StepContribution: read=1, written=1, filtered=0, readSkips=0, writeSkips=0, processSkips=0, exitStatus=EXECUTING]
o.s.j.d.DataSourceTransactionManager     : Participating in existing transaction
o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL update
o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [UPDATE BATCH_STEP_EXECUTION_CONTEXT SET SHORT_CONTEXT = ?, SERIALIZED_CONTEXT = ? WHERE STEP_EXECUTION_ID = ?]
o.s.jdbc.core.JdbcTemplate               : SQL update affected 1 rows
o.s.batch.core.step.tasklet.TaskletStep  : Saving step execution before commit: StepExecution: id=158, version=1, name=sendMailStep1, status=STARTED, exitStatus=EXECUTING, readCount=1, filterCount=0, writeCount=1 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=1, rollbackCount=0, exitDescription=
o.s.j.d.DataSourceTransactionManager     : Participating in existing transaction
o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL update
o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [UPDATE BATCH_STEP_EXECUTION set START_TIME = ?, END_TIME = ?, STATUS = ?, COMMIT_COUNT = ?, READ_COUNT = ?, FILTER_COUNT = ?, WRITE_COUNT = ?, EXIT_CODE = ?, EXIT_MESSAGE = ?, VERSION = ?, READ_SKIP_COUNT = ?, PROCESS_SKIP_COUNT = ?, WRITE_SKIP_COUNT = ?, ROLLBACK_COUNT = ?, LAST_UPDATED = ? where STEP_EXECUTION_ID = ? and VERSION = ?]
o.s.jdbc.core.JdbcTemplate               : SQL update affected 1 rows
o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL query
o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [SELECT VERSION FROM BATCH_JOB_EXECUTION WHERE JOB_EXECUTION_ID=?]
o.s.orm.jpa.EntityManagerFactoryUtils    : Closing JPA EntityManager
o.s.j.d.DataSourceTransactionManager     : Initiating transaction commit
o.s.j.d.DataSourceTransactionManager     : Committing JDBC transaction on Connection [ProxyConnection[PooledConnection[ConnectionID:10 ClientConnectionId: fe7a8cc9-6dcd-4e4c-95d4-ac426b633feb]]]
o.s.j.d.DataSourceTransactionManager     : Releasing JDBC Connection [ProxyConnection[PooledConnection[ConnectionID:10 ClientConnectionId: fe7a8cc9-6dcd-4e4c-95d4-ac426b633feb]]] after transaction
o.s.jdbc.datasource.DataSourceUtils      : Returning JDBC Connection to DataSource
enter code here

【问题讨论】:

  • 您确定您使用的是同一个数据源实例,而不是具有相同配置的第二个实例。从您所写的内容来看,似乎存储库数据源不是事务的一部分,这只有在与将 j 写入批处理存储库的数据源不同时才有可能。
  • 感谢您的回复!好点,我只查看了 ds 参数...。我刚刚检查了一下,SimpleJobRepository (-> JdbCStepExecutionDao -> jdbcTemplate) 和 MailRepository (DataSourceConnectionPool) 都指向具有相同实例 id 的同一个 DataSource ..

标签: spring-batch


【解决方案1】:

发现问题:我配置了 2 个 entityManagerFactories,因为我有 2 个数据源并希望使用实体和存储库。 我没有命名主要的“entityManagerFactory”,到目前为止没有任何问题。将此名称更改为默认名称解决了我的问题 - 但我想知道为什么这之前部分工作,没有任何例外......

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-25
    • 1970-01-01
    • 2021-05-17
    • 2019-01-31
    • 2022-10-17
    • 1970-01-01
    • 2014-04-23
    • 1970-01-01
    相关资源
    最近更新 更多