情報が先頭に表示されます。私はちょうど私が必要と思うコードスニペットを選択しました、彼らは別のファイルに存在するので、少し混乱しているように見えるのではないかと思いません。選択中のスプリングバッチ+休止状態の書き込み
ジョブのSpringBatch Readerでフラットファイルから読んでいます。 カラムをHibernateモデルにマップするFieldSetMapperから呼び出されたProductValueMapperを書きました。このマッパーは、製品がデータベースにすでに存在するかどうかをチェックし、存在する場合はデータベースのエンティティを使用します。そうでない場合、新しい製品が作成されます。
@Component
@StepScope
public class ProductValueMapper {
@Autowired
private IProductDao productDao;
@Autowired
private IFactory<Product> productFactory;
private Product fetch(String[] criteria) {
//... try to fetch product using different criteria, or create a new one using the factory ...
return product;
}
Product map(String[] criteria) {
Product product = fetch(criteria);
//... map some stuff ...
return product;
}
}
DAOのエンティティマネージャが
@PersistenceContext
private EntityManager manager;
によってAutowired取得し、その後@Transactional
としてマークされている私は、ロギングnothingexceptないプロセッサを持っています。
それから私はこのように作成されると、デフォルトjpaItemWriterに書き込む:> 1のチャンクと、私は問題を取得するバッチ中に変更されます項目とする以外は期待通りのプログラムが動作する
@Configuration
@Import(DatabaseConfiguration.class)
public class HibernateConfiguration extends DefaultBatchConfigurer {
@Autowired
@Qualifier("oracleDataSource")
private DataSource dataSource;
@Bean(name = "jpaEntitiyManager")
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setPersistenceUnitName("hibernatePersistenceUnit");
em.setPackagesToScan("com.somepackage");
em.setDataSource(dataSource);
em.setJpaProperties(hibernateProperties());
HibernateJpaVendorAdapter vendor = new HibernateJpaVendorAdapter();
vendor.setGenerateDdl(false);
vendor.setShowSql(true);
em.setJpaVendorAdapter(vendor);
return em;
}
@Bean
public Properties hibernateProperties() {
Properties prop = new Properties();
prop.setProperty("hibernate.hbm2ddl.auto", "validate");
prop.setProperty("hibernate.dialect", "org.hibernate.dialect.Oracle10gDialect");
prop.setProperty("hibernate.globally_quoted_identifiers", "false");
prop.setProperty("hibernate.show_sql", "true");
return prop;
}
@Override
public PlatformTransactionManager getTransactionManager() {
final JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return transactionManager;
}
}
@Configuration
@EnableBatchProcessing(modular = true)
@ComponentScan({"com.somepackage"})
@Import({HibernateConfiguration.class, DatabaseConfiguration.class})
public class BatchConfiguration {
@Autowired
public EntityManagerFactory emf;
@Bean
public JpaItemWriter<ProductEntity> jpaItemWriter() {
JpaItemWriter<ProductEntity> itemWriter = new JpaItemWriter<>();
itemWriter.setEntityManagerFactory(emf);
return itemWriter;
}
//... rest of the setup for the job
}
次の項目を選択している間は、hibernateはupdate文を実行します。
私はこれを解決するには、flushを呼び出してプロセッサに保存するか、チャンクサイズを1に減らすことができますが、どうにかして両方の解決策が間違っていると感じています。 アイテムごとにトランザクションを開いたままにしてはいけません。そして、ライターに電話をかけたら、これらのトランザクションは1つずつコミットされるべきですか?または、Spring Batchでトランザクションの処理の原則を誤解していますか?
* EDIT 1 *
問題は1にチャンクサイズを設定すると、期待どおりプログラムが動作することである:更新は、書き込みフェーズ中に発生します。
2016-09-05 11:20:40.828 INFO 11084 --- [ main] n.e.p.i.logging.LogItemReadListener : ItemReadListener - beforeRead
2016-09-05 11:20:40.828 INFO 11084 --- [ main] n.e.p.i.r.map.GenericProductMapper : Processing product: Prduct1
Hibernate: select productent0_.PRODUCTSN as PRODUCTSN1_25_, .....
2016-09-05 11:20:40.832 INFO 11084 --- [ main] n.e.p.i.logging.LogItemReadListener : ItemReadListener - afterRead: [email protected]
2016-09-05 11:20:40.832 INFO 11084 --- [ main] n.e.p.i.logging.LogItemWriterListener : ItemWriteListener - beforeWrite
Hibernate: update PIME.PRODUCT set AVAILABILITYDATE=?, ....
2016-09-05 11:20:40.836 INFO 11084 --- [ main] n.e.p.i.logging.LogItemWriterListener : ItemWriteListener - afterWrite
2016-09-05 11:20:40.887 INFO 11084 --- [ main] n.e.p.i.logging.LogItemReadListener : ItemReadListener - beforeRead
2016-09-05 11:20:40.887 INFO 11084 --- [ main] n.e.p.i.r.map.GenericProductMapper : Processing product: Product2
Hibernate: select productent0_.PRODUCTSN as PRODUCTSN1_25_, ....
2016-09-05 11:20:40.891 INFO 11084 --- [ main] n.e.p.i.logging.LogItemReadListener : ItemReadListener - afterRead: c[email protected]
2016-09-05 11:20:40.891 INFO 11084 --- [ main] n.e.p.i.logging.LogItemWriterListener : ItemWriteListener - beforeWrite
2016-09-05 11:20:40.891 INFO 11084 --- [ main] n.e.p.i.logging.LogItemWriterListener : ItemWriteListener - afterWrite
しかし、チャンクサイズを大きくした場合、書き込みは、製品の処理の最後ではなくチャンクで発生しませんので、書き込みは、select文のforntで起こる:
2016-09-05 11:09:36.240 INFO 12408 --- [ main] n.e.p.i.logging.LogItemReadListener : ItemReadListener - beforeRead
2016-09-05 11:09:36.240 INFO 12408 --- [ main] n.e.p.i.r.map.GenericProductMapper : Processing product: Product1
Hibernate: select productent0_.PRODUCTSN as PRODUCTSN1_25_, ....
2016-09-05 11:09:36.244 INFO 12408 --- [ main] n.e.p.i.logging.LogItemReadListener : ItemReadListener - afterRead: [email protected]
2016-09-05 11:09:36.244 INFO 12408 --- [ main] n.e.p.i.logging.LogItemReadListener : ItemReadListener - beforeRead
2016-09-05 11:09:36.244 INFO 12408 --- [ main] n.e.p.i.r.map.GenericProductMapper : Processing product: Product2
Hibernate: update PIME.PRODUCT set AVAILABILITYDATE=?, ....
Hibernate: select productent0_.PRODUCTSN as PRODUCTSN1_25_, ....
2016-09-05 11:09:36.250 INFO 12408 --- [ main] n.e.p.i.logging.LogItemReadListener : ItemReadListener - afterRead: [email protected]
2016-09-05 11:09:36.250 INFO 12408 --- [ main] n.e.p.i.logging.LogItemReadListener : ItemReadListener - beforeRead
2016-09-05 11:09:36.250 INFO 12408 --- [ main] n.e.p.i.r.map.GenericProductMapper : Processing product: Product3
Hibernate: select productent0_.PRODUCTSN as PRODUCTSN1_25_, ....
2016-09-05 11:09:36.253 INFO 12408 --- [ main] n.e.p.i.logging.LogItemReadListener : ItemReadListener - afterRead: [email protected]
2016-09-05 11:09:36.253 INFO 12408 --- [ main] n.e.p.i.logging.LogItemReadListener : ItemReadListener - beforeRead
2016-09-05 11:09:36.253 INFO 12408 --- [ main] n.e.p.i.r.map.GenericProductMapper : Processing product: Product4
Hibernate: select productent0_.PRODUCTSN as PRODUCTSN1_25_, ....
2016-09-05 11:09:36.256 INFO 12408 --- [ main] n.e.p.i.logging.LogItemReadListener : ItemReadListener - afterRead: [email protected]
2016-09-05 11:09:36.256 INFO 12408 --- [ main] n.e.p.i.logging.LogItemWriterListener : ItemWriteListener - beforeWrite
2016-09-05 11:09:36.257 INFO 12408 --- [ main] n.e.p.i.logging.LogItemWriterListener : ItemWriteListener - afterWrite
あなたはだけでなく、私にフェッチ()メソッドを示すことができました作家? –
本質的にfetchメソッドは、IDおよび異なる他の基準で製品を検索するためにDaoを使用します。例えばproductDao.getById(criteria [0])。それが空のままであれば、最終的にnew Product()を返すことになるファクトリからcreate()を呼び出します。完全なメソッドはいくつかの制約をチェックし、異なる条件に基づいてfindByを実行しますが、それを掲示したくなかった。ライターは、最後のコードエントリの最後にあります。これは単にデフォルトのJpaItemWriterです。 – Xtroce
さて、「バッチ中に変更されたアイテムは、次のアイテムを選択しているときに、Hibernateが更新ステートメントを実行するという問題が発生します。 ?私は理解の一種ですが、私はかなりではありません。問題を正確に明確にしてください(スタックトレースと例外は必要ならば) –