[SPRING] 트랜잭션을 위해 JPA EntityManager를 열 수 없습니다. 상자의 예외는 java.lang.IllegalStateException입니다.
SPRING트랜잭션을 위해 JPA EntityManager를 열 수 없습니다. 상자의 예외는 java.lang.IllegalStateException입니다.
나는 특히 Spring과 Spring-Batch에 상당히 익숙하다. 아직도 나는 어떻게 든 Spring Batch-Admin을 설치할 수 있었다. 지속성을 위해 사용자 정의 작업과 Hibernate / JPA를 추가했습니다.
첫 번째 청크가 유지되어야하는 시점까지 모든 것이 예상대로 작동합니다. 그런 다음 다음과 같은 오류 메시지가 나타납니다.
org.springframework.transaction.CannotCreateTransactionException:
Could not open JPA EntityManager for transaction;
nested exception is java.lang.IllegalStateException: Already value
[org.springframework.jdbc.datasource.ConnectionHolder@60d31437]
for key [org.springframework.jdbc.datasource.DriverManagerDataSource@12da4b19]
bound to thread [jobLauncherTaskExecutor-1]
다음은 전체 스택 추적입니다.
org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is java.lang.IllegalStateException: Already value [org.springframework.jdbc.datasource.ConnectionHolder@43f9e588] for key [org.springframework.jdbc.datasource.DriverManagerDataSource@84f171a] bound to thread [jobLauncherTaskExecutor-1]
at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:427)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:371)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:335)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:105)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at com.sun.proxy.$Proxy41.saveIfUnique(Unknown Source)
at com.qompa.batch.ArticleItemWriter.write(ArticleItemWriter.java:28)
at org.springframework.batch.core.step.item.SimpleChunkProcessor.writeItems(SimpleChunkProcessor.java:171)
at org.springframework.batch.core.step.item.SimpleChunkProcessor.doWrite(SimpleChunkProcessor.java:150)
at org.springframework.batch.core.step.item.FaultTolerantChunkProcessor$3.doWithRetry(FaultTolerantChunkProcessor.java:313)
at org.springframework.batch.retry.support.RetryTemplate.doExecute(RetryTemplate.java:240)
at org.springframework.batch.retry.support.RetryTemplate.execute(RetryTemplate.java:187)
at org.springframework.batch.core.step.item.BatchRetryTemplate.execute(BatchRetryTemplate.java:213)
at org.springframework.batch.core.step.item.FaultTolerantChunkProcessor.write(FaultTolerantChunkProcessor.java:402)
at org.springframework.batch.core.step.item.SimpleChunkProcessor.process(SimpleChunkProcessor.java:194)
at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:74)
at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:386)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:130)
at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:264)
at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:76)
at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:367)
at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:214)
at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:143)
at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:250)
at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:195)
at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:135)
at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:61)
at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:60)
at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:144)
at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:124)
at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:135)
at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:281)
at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:120)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
Caused by: java.lang.IllegalStateException: Already value [org.springframework.jdbc.datasource.ConnectionHolder@43f9e588] for key [org.springframework.jdbc.datasource.DriverManagerDataSource@84f171a] bound to thread [jobLauncherTaskExecutor-1]
at org.springframework.transaction.support.TransactionSynchronizationManager.bindResource(TransactionSynchronizationManager.java:189)
at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:402)
... 36 more
동일한 Job이 독립 실행 형 응용 프로그램에서 잘 실행됩니다. 이 문제는 Spring-Batch-Admin 환경에서만 발생합니다. 아래에서 프로젝트 구조 및 종속성을 볼 수 있습니다.
이는 Batch-Admin 구성을 재정의 / 확장하는 app-context.xml입니다.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:batch="http://www.springframework.org/schema/batch"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:task="http://www.springframework.org/schema/task" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch-2.1.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd">
<context:component-scan base-package="com.company.batch" />
<context:property-placeholder location="classpath:batch.properties" />
<import resource="classpath:/META-INF/spring/batch/jobs/article-job.xml" />
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${batch.jdbc.driver}" />
<property name="url" value="${batch.jdbc.url}" />
<property name="username" value="${batch.jdbc.user}" />
<property name="password" value="${batch.jdbc.password}" />
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.qompa.batch" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="POSTGRESQL"></property>
<property name="showSql" value="true" />
<property name="generateDdl" value="false" />
<property name="databasePlatform" value="com.company.utils.persistence.CustomPGDialect" />
</bean>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto"></prop>
</props>
</property>
</bean>
<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="txManager" />
<!-- schedule tasks -->
<task:scheduled-tasks>
<task:scheduled ref="articleRetrieval" method="run"
cron="0 0 */4 * * *" />
<task:scheduled ref="articleConversion" method="run"
cron="0 15 */4 * * *" />
</task:scheduled-tasks>
</beans>
지금까지 내가 이해 한 것은 jobLauncherTaskExecutor 빈이 참조하는 ThreadPoolTaskExecutor와 관련이 있다는 것입니다. 그것은 동시에 작업을 실행하기위한 연결 풀링을 처리하는 것 같다 ...하지만 솔직히 말해서 이런 것들을 작동하도록 구성을 변경하는 방법에 대한 단서가 없다.
[편집] : 저는 그것이 더 확실한 것은 ThreadPoolTaskExecutor입니다. 하지만 그것은 TaskExecutor 인터페이스의 구현 인 것처럼 보입니다.
누군가가 유사한 문제에 부딪혔거나 내 영속성 메소드를 위해 트랜잭션을 생성 할 수있는 방법으로 내 애플리케이션을 구성하는 방법에 대한 제안이 있다면 : 힌트를주세요!
해결법
-
==============================
1.이 오류는 JpaTransactionManager 403 행에 있습니다.
이 오류는 JpaTransactionManager 403 행에 있습니다.
TransactionSynchronizationManager.bindResource(getDataSource(), conHolder);
이 오류는 트랜잭션 관리자가 엔티티 관리자가 아닌 데이터 소스를 스레드에 바인드하려고하지만 데이터 소스가 이미 있고 예상치 못한 결과라는 것을 의미합니다.
트랜잭션 관리자는 Entity Manager를 스레드에 아직 바인딩하지 않았으며 JpaTransactionManager 줄 416에서 다음에 발생합니다.
가능한 설명은 두 가지입니다.
한 가지 질문은 하나의 실행 스레드에서만 발생합니까 아니면 여러 개의 실행 스레드에서 발생합니까?
문제가 무엇인지 알아 내려면 다음 단계를 수행하십시오.
-
==============================
2.이것은 일반적으로 여러 트랜잭션 관리자가있는 경우에 발생합니다.
이것은 일반적으로 여러 트랜잭션 관리자가있는 경우에 발생합니다.
-
==============================
3.이러한 종류의 문제는 jdk 6 또는 더 낮은 버전과 같은 java의 이전 버전에서 발생합니다 .7 이상으로 jdk 버전을 업그레이드하십시오. 심지어 jdk 버전을 7로 업데이트했을 때도 이전과 같은 문제가 발생했습니다.
이러한 종류의 문제는 jdk 6 또는 더 낮은 버전과 같은 java의 이전 버전에서 발생합니다 .7 이상으로 jdk 버전을 업그레이드하십시오. 심지어 jdk 버전을 7로 업데이트했을 때도 이전과 같은 문제가 발생했습니다.
-
==============================
4.JPA 용 스프링 배치 구성을 구현하여 비슷한 문제를 해결할 수있었습니다.
JPA 용 스프링 배치 구성을 구현하여 비슷한 문제를 해결할 수있었습니다.
import javax.annotation.PostConstruct; import javax.inject.Inject; import javax.sql.DataSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.batch.core.configuration.BatchConfigurationException; import org.springframework.batch.core.configuration.annotation.BatchConfigurer; import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; import org.springframework.batch.core.explore.JobExplorer; import org.springframework.batch.core.explore.support.JobExplorerFactoryBean; import org.springframework.batch.core.explore.support.MapJobExplorerFactoryBean; import org.springframework.batch.core.launch.JobLauncher; import org.springframework.batch.core.launch.support.SimpleJobLauncher; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean; import org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean; import org.springframework.batch.support.transaction.ResourcelessTransactionManager; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.task.SimpleAsyncTaskExecutor; import org.springframework.transaction.PlatformTransactionManager; @Configuration public class JpaBatchConfigurer implements BatchConfigurer { private static final Logger logger = LoggerFactory .getLogger(JpaBatchConfigurer.class); @Inject private DataSource dataSource; @Inject private PlatformTransactionManager transactionManager; private JobRepository jobRepository; private JobLauncher jobLauncher; private JobExplorer jobExplorer; protected JpaBatchConfigurer() { } @Override @Bean public JobRepository getJobRepository() { return jobRepository; } @Override public PlatformTransactionManager getTransactionManager() { return transactionManager; } @Override @Bean public JobLauncher getJobLauncher() { return jobLauncher; } @Override @Bean public JobExplorer getJobExplorer() { return jobExplorer; } @PostConstruct public void initialize() { try { if (dataSource == null) { logger.warn("No datasource was provided...using a Map based JobRepository"); if (this.transactionManager == null) { this.transactionManager = new ResourcelessTransactionManager(); } MapJobRepositoryFactoryBean jobRepositoryFactory = new MapJobRepositoryFactoryBean( this.transactionManager); jobRepositoryFactory.afterPropertiesSet(); this.jobRepository = jobRepositoryFactory.getObject(); MapJobExplorerFactoryBean jobExplorerFactory = new MapJobExplorerFactoryBean( jobRepositoryFactory); jobExplorerFactory.afterPropertiesSet(); this.jobExplorer = jobExplorerFactory.getObject(); } else { this.jobRepository = createJobRepository(); JobExplorerFactoryBean jobExplorerFactoryBean = new JobExplorerFactoryBean(); jobExplorerFactoryBean.setDataSource(this.dataSource); jobExplorerFactoryBean.afterPropertiesSet(); this.jobExplorer = jobExplorerFactoryBean.getObject(); } this.jobLauncher = createJobLauncher(); } catch (Exception e) { throw new BatchConfigurationException(e); } } private JobLauncher createJobLauncher() throws Exception { SimpleJobLauncher jobLauncher = new SimpleJobLauncher(); jobLauncher.setJobRepository(jobRepository); jobLauncher.setTaskExecutor( new SimpleAsyncTaskExecutor()); jobLauncher.afterPropertiesSet(); return jobLauncher; } protected JobRepository createJobRepository() throws Exception { JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); factory.setIsolationLevelForCreate("ISOLATION_SERIALIZABLE"); factory.setDataSource(dataSource); factory.setTransactionManager(transactionManager); factory.setValidateTransactionState(false); factory.afterPropertiesSet(); return factory.getObject(); } @Bean public JobBuilderFactory jobBuilderFactory(JobRepository jobRepository){ return new JobBuilderFactory(jobRepository); } @Bean public StepBuilderFactory stepBuilderFactory(JobRepository jobRepository, PlatformTransactionManager transactionManager){ return new StepBuilderFactory(jobRepository, transactionManager); } }
https : //github.com/hantsy/spring4-sandbox/blob/master/batch-jpa/src/main/java/com/hantsylabs/example/spring/config/JpaBatchConfigurer.java에서 복사했습니다.
from https://stackoverflow.com/questions/20907206/could-not-open-jpa-entitymanager-for-transaction-nested-exception-is-java-lang by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] Spring WS : XSD 유효성 검사 오류를 얻고 저장하는 방법 (0) | 2019.04.16 |
---|---|
[SPRING] 다른 저장소에서 Maven Eclipse 플러그인으로 소스 및 javadoc 아티팩트를 다운로드하는 방법은 무엇입니까? (0) | 2019.04.16 |
[SPRING] Spring과 Thymeleaf를 사용한 로그 아웃 링크 (0) | 2019.04.16 |
[SPRING] Spring 부트 2.0.0 이후의 "튜플과 앨리어스의 크기가 다릅니다"예외. (0) | 2019.04.16 |
[SPRING] 스프링 부트로 Gradle.build 버전 가져 오기 (0) | 2019.04.16 |