简体   繁体   English

Spring Batch无法打开JPA EntityManager进行事务处理; 嵌套异常是java.lang.IllegalStateException:事务已处于活动状态

[英]Spring Batch Could not open JPA EntityManager for transaction; nested exception is java.lang.IllegalStateException: Transaction already active

My Spring Batch job is started every 5 minutes - basically it reads a string, uses the string as a parameter in a sql query, and prints out the resulting sql result list. 我的Spring Batch作业每5分钟启动一次 - 基本上它读取一个字符串,在sql查询中使用该字符串作为参数,并打印出生成的sql结果列表。 Mostly it seems to be running ok, but I notice sporadic errors in my logs every 5-10 runs 大多数情况下它似乎运行正常,但我发现每5-10次运行我的日志中偶然出现错误

2017-05-05 11:13:26.101  INFO 9572 --- [nio-8081-exec-8] c.u.r.s.AgentCollectorServiceImpl    : Could not open JPA E
ntityManager for transaction; nested exception is java.lang.IllegalStateException: Transaction already active

My job is started like from my AgentCollectorServiceImpl class 我的工作是从我的AgentCollectorServiceImpl类开始的

@Override
public void addReportIds(List<Integer> reportIds) {
    try {
            .toJobParameters();
        jobLauncher.run(job, jobParameters);
    } catch (Exception e) {
        log.info(e.getMessage());
    }
}

My BatchConfig class looks like 我的BatchConfig类看起来像

@Configuration
@EnableBatchProcessing
@Import(AppConfig.class)
public class BatchConfig {

    @Autowired
    private JobBuilderFactory jobBuilderFactory;

    @Autowired
    private StepBuilderFactory stepBuilderFactory;

    @Autowired
    private AppConfig appConfig;

    @Bean
    public Reader reader() {
        return new Reader();
    }

    @Bean
    public Processor processor() {
        return new Processor();
    }

    @Bean
    public Writer writer() {
        return new Writer();
    }

    @Bean
    public Job job() {
        return jobBuilderFactory.get("job")
            .incrementer(new RunIdIncrementer())
            .flow(step1())
            .end()
            .build();
    }

    @Bean
    public Step step1() {
        return stepBuilderFactory.get("step1")
            .<String, String> chunk(1)
            .reader(reader())
            .processor(processor())
            .writer(writer())
            .build();
    }
}

My AppConfig class looks like 我的AppConfig类看起来像

@Configuration
@PropertySource("classpath:application.properties")
@ComponentScan
public class AppConfig {


    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(organizationDataSource());
        em.setPackagesToScan(new String[]{"com.organization.agentcollector.model"});
        JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        em.setJpaVendorAdapter(vendorAdapter);
        em.setJpaProperties(additionalProperties());

        return em;
    }

    Properties additionalProperties() {
        Properties properties = new Properties();
        properties.setProperty("hibernate.dialect", "com.organization.agentcollector.config.SQLServerDialectOverrider");
        return properties;
    }
    @Bean
    JpaTransactionManager transactionManager(final EntityManagerFactory emf) {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
        return transactionManager;
    }

My Processor class looks like 我的处理器类看起来像

public class Processor implements ItemProcessor<String, String> {

    private final Logger log = LoggerFactory.getLogger(Processor.class);

    @Autowired
    EventReportsDAOImpl eventReportsDAOImpl;

    @Override
    public String process(String reportIdsJson) throws Exception {

        String eventReportsJson = eventReportsDAOImpl.listEventReportsInJsonRequest(reportIdsJson);
        //System.out.println(returnContent+"PROCESSOR");
        return eventReportsJson;
    }

}

My DAOImpl class looks like 我的DAOImpl类看起来像

@Component
@Transactional
public class EventReportsDAOImpl implements EventReportsDAO {

    @PersistenceContext
    private EntityManager em;

    @Override
    public EventReports getEventReports(Integer reportId) {
        return null;
    }

    @Override
    public String listEventReportsInJsonRequest(String reportIds) {

        System.out.println("Event Report reportIds processing");
        ArrayList<EventReports> erArr = new ArrayList<EventReports>();
        String reportIdsList = reportIds.substring(1, reportIds.length() - 1);
        //System.out.println(reportIdsList);

        try {
            StoredProcedureQuery q = em.createStoredProcedureQuery("sp_get_event_reports", "eventReportsResult");
            q.registerStoredProcedureParameter("reportIds", String.class, ParameterMode.IN);
            q.setParameter("reportIds", reportIdsList);
            boolean isResultSet = q.execute();  
            erArr = (ArrayList<EventReports>) q.getResultList();
        } catch (Exception e) {
            System.out.println("No event reports found for list " + reportIdsList);
        }

        return erArr.toString();
    }

I thought Spring would manage transactions automatically. 我以为Spring会自动管理交易。 The error seems to suggest that a transaction is not being properly closed? 该错误似乎表明交易未正确关闭?

One thing I tried was removing all @Transactional annotations from my code as I read that @EnableBatchProcessing already injects a Transaction Manager into each step - but when I did this, I saw the 'transaction already active' error much more frequently. 我尝试过的一件事是从我的代码中删除所有@Transactional注释,因为我读到@EnableBatchProcessing已经在每一步中注入了一个事务管理器 - 但是当我这样做时,我更频繁地看到'事务已经激活'错误。

Any advice appreciated on how to fix this, thank you! 任何建议对如何解决这个问题表示赞赏,谢谢!

The @Transactional notation establishes a transactional scope that dictates when a transaction starts and ends, also called its boundary. @Transactional表示法建立一个事务范围 ,指示事务何时开始和结束,也称为其边界。 If you operate outside of this boundary you'll receive errors. 如果您在此边界之外操作,您将收到错误。

First off, I found this bit of documentation the most helpful on Spring transactions: http://docs.spring.io/spring-framework/docs/4.2.x/spring-framework-reference/html/transaction.html specifically this section 首先,我发现这些文档对Spring事务最有帮助: http//docs.spring.io/spring-framework/docs/4.2.x/spring-framework-reference/html/transaction.html具体这一部分

Secondly, you may wish to enable trace level logs and potentially the SQL statements to help debug this. 其次,您可能希望启用跟踪级别日志以及可能的SQL语句来帮助调试此问题。 In order to do so I added the following to my application.properties : 为此,我将以下内容添加到我的application.properties

spring.jpa.properties.hibernate.show_sql=false
spring.jpa.properties.hibernate.use_sql_comments=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.type=trace
spring.jpa.show-sql=true
logging.level.org.hibernate=TRACE

There will be ALOT of output here, but you'll get a good idea of whats happening behind the scenes. 这里会有很多输出,但你会很好地了解幕后发生的事情。

Third, and the most important part for me in learning how to use @Transactional is that every call to the DAO creates a new session -or- reuses the existing session if within the same transactional scope. 第三,对我来说,学习如何使用@Transactional最重要的部分是每次调用DAO都会创建一个新会话 - 或者 - 如果在同一个事务范围内,则重用现有会话。 Refer to the documentation above for examples of this. 有关此示例,请参阅上面的文档。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 无法为事务嵌套异常打开 JPA EntityManager 为 java.lang.IllegalStateException:已为键绑定到线程的值 - Could not open JPA EntityManager for transaction nested exception is java.lang.IllegalStateException:Already value for key bound to thread 无法为事务打开 JPA EntityManager; 嵌套异常是 java.lang.IllegalStateException - Could not open JPA EntityManager for transaction; nested exception is java.lang.IllegalStateException 无法为事务打开 JPA EntityManager; 嵌套异常是 java.lang.NoSuchMethodError - Spring-Starter-JPA - Could not open JPA EntityManager for transaction; nested exception is java.lang.NoSuchMethodError - Spring-Starter-JPA Spring batch spring jpa 错误 CannotCreateTransactionException: Could not open JPA EntityManager for transaction IllegalStateException: - Spring batch spring jpa error CannotCreateTransactionException: Could not open JPA EntityManager for transaction IllegalStateException: 无法打开 jpa 实体管理器进行事务处理。 嵌套异常是 java.lang.nosuchmethod 错误 - Could not open jpa entitymanager for transaction. nested exception is java.lang.nosuchmethod error java.lang.IllegalStateException:事务在 session.beginTransaction() 处已处于活动状态 - java.lang.IllegalStateException: Transaction already active at session.beginTransaction() Hibernate java.lang.IllegalStateException:事务已经激活 - Hibernate java.lang.IllegalStateException: Transaction already active java.lang.IllegalStateException:事务未激活 - java.lang.IllegalStateException: transaction is not active 异常“java.lang.IllegalStateException:在 JobRepository 中检测到现有事务。” 将 Spring Batch 从 2.1.1 升级到 4.1.1 版本后 - Exception "java.lang.IllegalStateException: Existing transaction detected in JobRepository." after upgrading spring batch from 2.1.1 to 4.1.1 version 如何防止错误 java.lang.IllegalStateException: Transaction already active, in Hibernate - How to prevent the error java.lang.IllegalStateException: Transaction already active, in Hibernate
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM