Spring 批处理、单元测试、JPA 事务和 Hibernate 延迟加载:IllegalTransactionStateException
Spring batch, Unit test, JPA Transaction and Hibernate Lazy loading : IllegalTransactionStateException
伙计们,
我想 运行 一个 spring 批处理作业,然后对生成的数据进行一些测试,但我需要使用休眠延迟加载。所以我需要一个打开的事务来保持会话活动。
但我得到这个异常:IllegalTransactionStateException:预绑定 JDBC 找到连接!
我可以编写方法来直接获取我想要测试的关联对象,但我不想编写仅用于测试的方法并失去 hibernate 的优势。
有办法吗?我尝试在 jobRepositoy 中将 validateStateTransaction 设置为 false,但它不起作用(实际上它只适用于内存中的元数据存储库,如 MapJobRepository)。
我搜索了几天,但没有任何效果。
你能帮帮我吗?谢谢
我的代码在这里:
<bean id="jobRepository"
class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean">
<property name="databaseType">
<value>POSTGRES</value>
</property>
<property name="dataSource" ref="databasePool" />
<property name="transactionManager" ref="transactionManager" />
<property name="isolationLevelForCreate" value="ISOLATION_DEFAULT" />
<property name="tablePrefix" value="#{ schema }.BATCH_" />
<property name="validateTransactionState" value="false" />
</bean>
和
@Test
@Transactional
public void test() {
/*
* ===================RUN JOB======================
*/
JobParameters jobParameters = new JobParametersBuilder();
int returnCode = runJob("job_name", jobParameters);
assertEquals("returnCode must be 0.", 0, returnCode );
/*
* ===============END JOB=============================
*/
/*
* ===============TEST ON DATA==========================
*/
ObjectToTest obj = objectDao.findById("1");
assertNotNull( obj.getSomeCollection().get(1));
/*
* =================END TEST==================
*/
}
这里是例外情况:
org.springframework.transaction.IllegalTransactionStateException: Pre-bound JDBC Connection found! JpaTransactionManager does not support running within DataSourceTransactionManager if told to manage the DataSource itself. It is recommended to use a single JpaTransactionManager for all transactions on a single DataSource, no matter whether JPA or JDBC access.
at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:359)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:438)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:261)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy113.getLastJobExecution(Unknown Source)
at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:98)
at org.springframework.batch.core.launch.support.CommandLineJobRunner.start(CommandLineJobRunner.java:362)
at org.springframework.batch.core.launch.support.CommandLineJobRunner.main(CommandLineJobRunner.java:590)
at fr.insee.harmonica.commun.batch.CommandLineJobRunnerTest.runJob(CommandLineJobRunnerTest.java:143)
at fr.insee.harmonica.commun.batch.CommandLineJobRunnerTest.execute(CommandLineJobRunnerTest.java:420)
我尝试将测试部分放在另一个用@Transactional 注释的方法中,但随后我得到一个 LazyInitializationException...
编辑:
我使用 org.springframework.orm.jpa.JpaTransactionManager 事务管理器的实现。
这是我的 spring 配置:
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="myEmf" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
我已经搜索了手动开启交易的方法,但我没有找到
好的,我找到了解决方案(最终没有任何帮助)。
为此,您必须在工作结束后手动打开一个事务。
你可以这样做:
@Autowired
protected PlatformTransactionManager transactionManager;
@Test
public void test() {
/*
* ===================RUN JOB======================
*/
JobParameters jobParameters = new JobParametersBuilder();
int returnCode = runJob("job_name", jobParameters);
assertEquals("returnCode must be 0.", 0, returnCode );
/*
* ===============END JOB=============================
*/
/*
* ===============TEST ON DATA==========================
*/
(new TransactionTemplate(transactionManager)).execute(new TransactionCallback() {
@Override
public Object doInTransaction(TransactionStatus status) {
ObjectToTest obj = objectDao.findById("1");
assertNotNull( obj.getSomeCollection().get(1));
}
});
/*
* =================END TEST==================
*/
}
伙计们,
我想 运行 一个 spring 批处理作业,然后对生成的数据进行一些测试,但我需要使用休眠延迟加载。所以我需要一个打开的事务来保持会话活动。
但我得到这个异常:IllegalTransactionStateException:预绑定 JDBC 找到连接!
我可以编写方法来直接获取我想要测试的关联对象,但我不想编写仅用于测试的方法并失去 hibernate 的优势。
有办法吗?我尝试在 jobRepositoy 中将 validateStateTransaction 设置为 false,但它不起作用(实际上它只适用于内存中的元数据存储库,如 MapJobRepository)。
我搜索了几天,但没有任何效果。
你能帮帮我吗?谢谢
我的代码在这里:
<bean id="jobRepository"
class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean">
<property name="databaseType">
<value>POSTGRES</value>
</property>
<property name="dataSource" ref="databasePool" />
<property name="transactionManager" ref="transactionManager" />
<property name="isolationLevelForCreate" value="ISOLATION_DEFAULT" />
<property name="tablePrefix" value="#{ schema }.BATCH_" />
<property name="validateTransactionState" value="false" />
</bean>
和
@Test
@Transactional
public void test() {
/*
* ===================RUN JOB======================
*/
JobParameters jobParameters = new JobParametersBuilder();
int returnCode = runJob("job_name", jobParameters);
assertEquals("returnCode must be 0.", 0, returnCode );
/*
* ===============END JOB=============================
*/
/*
* ===============TEST ON DATA==========================
*/
ObjectToTest obj = objectDao.findById("1");
assertNotNull( obj.getSomeCollection().get(1));
/*
* =================END TEST==================
*/
}
这里是例外情况:
org.springframework.transaction.IllegalTransactionStateException: Pre-bound JDBC Connection found! JpaTransactionManager does not support running within DataSourceTransactionManager if told to manage the DataSource itself. It is recommended to use a single JpaTransactionManager for all transactions on a single DataSource, no matter whether JPA or JDBC access.
at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:359)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:438)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:261)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy113.getLastJobExecution(Unknown Source)
at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:98)
at org.springframework.batch.core.launch.support.CommandLineJobRunner.start(CommandLineJobRunner.java:362)
at org.springframework.batch.core.launch.support.CommandLineJobRunner.main(CommandLineJobRunner.java:590)
at fr.insee.harmonica.commun.batch.CommandLineJobRunnerTest.runJob(CommandLineJobRunnerTest.java:143)
at fr.insee.harmonica.commun.batch.CommandLineJobRunnerTest.execute(CommandLineJobRunnerTest.java:420)
我尝试将测试部分放在另一个用@Transactional 注释的方法中,但随后我得到一个 LazyInitializationException...
编辑:
我使用 org.springframework.orm.jpa.JpaTransactionManager 事务管理器的实现。
这是我的 spring 配置:
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="myEmf" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
我已经搜索了手动开启交易的方法,但我没有找到
好的,我找到了解决方案(最终没有任何帮助)。
为此,您必须在工作结束后手动打开一个事务。
你可以这样做:
@Autowired
protected PlatformTransactionManager transactionManager;
@Test
public void test() {
/*
* ===================RUN JOB======================
*/
JobParameters jobParameters = new JobParametersBuilder();
int returnCode = runJob("job_name", jobParameters);
assertEquals("returnCode must be 0.", 0, returnCode );
/*
* ===============END JOB=============================
*/
/*
* ===============TEST ON DATA==========================
*/
(new TransactionTemplate(transactionManager)).execute(new TransactionCallback() {
@Override
public Object doInTransaction(TransactionStatus status) {
ObjectToTest obj = objectDao.findById("1");
assertNotNull( obj.getSomeCollection().get(1));
}
});
/*
* =================END TEST==================
*/
}