Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用自定义编写器时,Spring批处理不会启动事务_Spring_Transactions_Spring Batch - Fatal编程技术网

使用自定义编写器时,Spring批处理不会启动事务

使用自定义编写器时,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

我正在处理一个spring批处理,它从csv文件读取数据并写入数据库。我使用FlatFileItemReader读取文件,并实现了ItemWriter,它使用Jpa将数据插入数据库。但批处理失败,没有正在进行的事务。 这是我的工作配置

<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;