gpt4 book ai didi

java - Spring Batch 无法打开 JPA EntityManager 进行事务;嵌套异常是 java.lang.IllegalStateException : Transaction already active

转载 作者:太空宇宙 更新时间:2023-11-04 11:30:55 25 4
gpt4 key购买 nike

我的 Spring Batch 作业每 5 分钟启动一次 - 基本上它读取一个字符串,使用该字符串作为 sql 查询中的参数,并打印出生成的 sql 结果列表。大多数情况下,它似乎运行正常,但我注意到每运行 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

我的工作是从我的 AgentCollectorServiceImpl 类开始的

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

我的 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();
}
}

我的 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;
}

我的处理器类看起来像

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

}

我的 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();
}

我以为 Spring 会自动管理事务。该错误似乎表明交易未正确关闭?

我尝试过的一件事是从代码中删除所有 @Transactional 注释,因为我读到 @EnableBatchProcessing 已经将事务管理器注入(inject)到每个步骤中 - 但当我这样做时,我更频繁地看到“事务已处于 Activity 状态”错误。

任何有关如何解决此问题的建议,谢谢!

最佳答案

@Transactional表示法建立了一个事务范围,它规定事务何时开始和结束,也称为其边界。如果您在此边界之外操作,您将收到错误。

首先,我发现这段文档对 Spring 事务最有帮助:http://docs.spring.io/spring-framework/docs/4.2.x/spring-framework-reference/html/transaction.html具体来说this section

其次,您可能希望启用跟踪级别日志以及可能的 SQL 语句来帮助调试此问题。为此,我将以下内容添加到我的 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

这里会有很多输出,但您会很好地了解幕后发生的事情。

第三,也是我学习如何使用@Transactional最重要的部分是对 DAO 的每次调用都会创建一个新 session ,或者如果在同一事务范围内,则重用现有 session 。有关示例,请参阅上面的文档。

关于java - Spring Batch 无法打开 JPA EntityManager 进行事务;嵌套异常是 java.lang.IllegalStateException : Transaction already active,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43809963/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com