使用自定义编写器时,Spring批处理不会启动事务
我正在处理一个spring批处理,它从csv文件读取数据并写入数据库。我使用FlatFileItemReader读取文件,并实现了ItemWriter,它使用Jpa将数据插入数据库。但批处理失败,没有正在进行的事务。 这是我的工作配置使用自定义编写器时,Spring批处理不会启动事务,spring,transactions,spring-batch,Spring,Transactions,Spring Batch,我正在处理一个spring批处理,它从csv文件读取数据并写入数据库。我使用FlatFileItemReader读取文件,并实现了ItemWriter,它使用Jpa将数据插入数据库。但批处理失败,没有正在进行的事务。 这是我的工作配置 <bean id="datasource" class="oracle.jdbc.pool.OracleDataSource"> <property name="user" value="xxx" /> <proper
<bean id="datasource" class="oracle.jdbc.pool.OracleDataSource">
<property name="user" value="xxx" />
<property name="password" value="xx" />
<property name="URL" value="xxx" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<bean id="entityManagerFactory" name="model"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="datasource"/>
<property name="jpaVendorAdapter">
<bean
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="generateDdl" value="false"/>
<property name="showSql" value="true"/>
<property name="database">
<util:constant
static-field="org.springframework.orm.jpa.vendor.Database.ORACLE"/>
</property>
<property name="databasePlatform" value="org.hibernate.dialect.Oracle12cDialect"/>
</bean>
</property>
</bean>
<batch:job id="testJob">
<batch:step id="step">
<batch:tasklet>
<batch:chunk reader="cvsFileItemReader" writer="databaseWriter"
commit-interval="10">
</batch:chunk>
</batch:tasklet>
</batch:step>
</batch:job>
下面是我的作者
public class DatabaseWriter implements ItemWriter<Report> {
private EntityManagerFactory entityManagerFactory;
@Autowired
public DatabaseWriter(EntityManagerFactory entityManagerFactory) {
this.entityManagerFactory = entityManagerFactory;
}
@Override
public void write(List<? extends Report> list) throws Exception {
EntityManager entityManager = entityManagerFactory.createEntityManager();
for (Report report : list) {
entityManager.persist(report );
}
entityManager.flush();
}
公共类DatabaseWriter实现ItemWriter{
私人实体管理工厂实体管理工厂;
@自动连线
公共数据库编写器(EntityManagerFactory EntityManagerFactory){
this.entityManagerFactory=entityManagerFactory;
}
@凌驾
public void write(List创建DAO并将您的JPA代码移动到那里,并在编写器中自动连接DAO
还要确保自动关联实体管理器,如下所示
@PersistenceContext
private EntityManager em;
创建DAO并将JPA代码移动到那里,然后在编写器中自动连接DAO
还要确保自动关联实体管理器,如下所示
@PersistenceContext
private EntityManager em;
但我很难理解这种行为的原因
第一种方法不起作用,因为当您的代码实际在Spring Batch驱动的事务范围内运行时,您需要手动创建事务。因此,将有两个具有不同上下文的事务
您应该记住,tasklet是在Spring批处理驱动的事务中执行的(包括面向块的tasklet的项编写器)。因此,在该范围内运行的任何代码都应该符合tasklet的事务定义。在您的情况下,写入器中注入的EntityManager
由您定义的JpaTransactionManager
驱动,Spring批处理也使用它来处理tasklet的事务
作为旁注,您可以使用Spring Batch提供的JpaItemWriter
,而不是编写自定义编写器。代码几乎相同
但我很难理解这种行为的原因
第一种方法不起作用,因为当您的代码实际在Spring Batch驱动的事务范围内运行时,您需要手动创建事务。因此,将有两个具有不同上下文的事务
您应该记住,tasklet是在Spring批处理驱动的事务中执行的(包括面向块的tasklet的项编写器)。因此,在该范围内运行的任何代码都应该符合tasklet的事务定义。在您的情况下,写入器中注入的EntityManager
由您定义的JpaTransactionManager
驱动,Spring批处理也使用它来处理tasklet的事务
作为旁注,您可以使用Spring Batch提供的JpaItemWriter
,而不是编写自定义编写器。代码几乎相同
@PersistenceContext
private EntityManager em;