我有一个玩具项目,它将人名和怪物名称列入数据库,然后使用然后将怪物的姓氏更改为Monster。要使用HibernateItemWriter
将项目写入数据库3个作业中的每一个都有自己的配置文件,它们捆绑在一个配置中,并带有@EnableBatchProcessing(modular = true)注释。
这一切都有效。
但是,当单个作业的配置文件中存在@EnableBatchProcessing时,HibernateItemWriter无法再找到hibernate会话。
有人可以解释实现这一目标的应用程序上下文范围规则吗?
在不单独使用它们时,在单个作业配置上使用@EnableBatchProcessing是相当不错的。它允许在弹簧自动配置完成工作时导入和运行它们。
申请
@Import({ImportAllConfiguration.class, EmbededDatasourceConfiguration.class, HibernateConfiguration.class})
@Configuration
public class Application {
public static void main(String[] args) throws SQLException, BeansException, JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException, NoSuchJobException, JobParametersInvalidException {
ApplicationContext ctx = SpringApplication.run(Application.class, args);
JobRegistry jobRegistry = ctx.getBean(JobRegistry.class);
Job job1 = jobRegistry.getJob("importMonsterJob");
JobLauncher launcher = ctx.getBean(JobLauncher.class);
launcher.run(job1, new JobParameters());
}
}
ImportAllConfiguration
@Configuration
@EnableBatchProcessing(modular=true)
public class ImportAllConfiguration {
@Bean
public ApplicationContextFactory someJobs() {
return new GenericApplicationContextFactory(ImportMonsterConfiguration.class);
}
@Bean
public ApplicationContextFactory someMoreJobs() {
return new GenericApplicationContextFactory(ImportPersonConfiguration.class);
}
@Bean
public ApplicationContextFactory evenMoreJobs() {
return new GenericApplicationContextFactory(MatchMonsterToPersonConfiguration.class);
}
}
Hibernate配置
@Configuration
public class HibernateConfiguration {
@Autowired
private DataSource dataSource;
@Bean
public HibernateTransactionManager transactionManager(
SessionFactory sessionFactory) {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(sessionFactory);
return txManager;
}
@Bean
public JdbcTemplate jdbcTemplate() {
JdbcTemplate jdbcTemplate = new JdbcTemplate();
jdbcTemplate.setDataSource(dataSource);
return jdbcTemplate;
}
@SuppressWarnings("serial")
public Properties hibernateProperties() {
return new Properties() {
{
//setProperty(Environment.CURRENT_SESSION_CONTEXT_CLASS, "thread");
setProperty(Environment.HBM2DDL_AUTO, "create");
setProperty(Environment.SHOW_SQL, "true");
}
};
}
@Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean annotationSessionFactoryBean = new LocalSessionFactoryBean();
annotationSessionFactoryBean.setPackagesToScan("hello.model");
annotationSessionFactoryBean.setDataSource(dataSource);
annotationSessionFactoryBean
.setHibernateProperties(hibernateProperties());
return annotationSessionFactoryBean;
}
}
作业配置文件。在这里添加@EnableBatchProcessing将导致HibernateItemWriter无法找到会话。
@Configuration
@EnableBatchProcessing <-- This causes the exception
public class ImportMonsterConfiguration {
@Autowired
protected SessionFactory sessionFactory;
@Autowired
protected StepBuilderFactory stepBuilderFactory;
@Autowired
protected JobBuilderFactory jobBuilderFactory;
@Bean
public <T> ItemWriter<T> writer() {
return new HibernateItemWriter<T>() {
{
setSessionFactory(sessionFactory);
}
};
}
@Bean
public ItemReader<Monster> reader() {
FlatFileItemReader<Monster> reader = new FlatFileItemReader<Monster>();
reader.setResource(new ClassPathResource("sample-data.csv"));
reader.setLineMapper(new DefaultLineMapper<Monster>() {
{
setLineTokenizer(new DelimitedLineTokenizer() {
{
setNames(new String[] { "firstName", "lastName" });
}
});
setFieldSetMapper(new BeanWrapperFieldSetMapper<Monster>() {
{
setTargetType(Monster.class);
}
});
}
});
return reader;
}
@Bean
public ItemProcessor<Monster, Monster> processor() {
return new MonsterItemProcessor();
}
@Bean
public Job importMonsterJob() {
return jobBuilderFactory.get("importMonsterJob")
.incrementer(new RunIdIncrementer()).flow(step2()).end()
.build();
}
@Bean
public LocalValidatorFactoryBean validator() {
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
return validator;
}
@Bean
public ItemProcessor<Monster, Monster> validatingProcessor() {
SpringValidator<Monster> springValidator = new SpringValidator<Monster>();
springValidator.setValidator(validator());
ValidatingItemProcessor<Monster> validatingItemProcessor = new ValidatingItemProcessor<Monster>();
validatingItemProcessor.setValidator(springValidator);
return validatingItemProcessor;
}
@Bean
public Step step2() {
return stepBuilderFactory.get("step2").<Monster, Monster> chunk(10)
.reader(reader()).processor(processor())
.processor(validatingProcessor()).writer(writer()).build();
}
}
抛出异常。
org.hibernate.HibernateException: No Session found for current thread
at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:106)
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:1014)
at org.springframework.batch.item.database.HibernateItemWriter.doWrite(HibernateItemWriter.java:134)
at org.springframework.batch.item.database.HibernateItemWriter.write(HibernateItemWriter.java:113)
答案 0 :(得分:2)
您提供自己的交易管理器。要覆盖Spring Batch随@EnableBatchProcessing
提供的那些,您需要提供自己的BatchConfigurer
实现。否则,我们将为您添加一个,在这种情况下,它不会成为基于Hibernate的事务管理器。 HibernateConfiguration
扩展DefaultBatchConfigurer
并使用您的事务管理器代码覆盖getTransactionManager
方法。