私は休止状態でjpaを使用します。私は次の方法があります:
_@Transactional
public void myMethod(){
...
firstJDBCTemplateQuery();
secondJDBCTemplateQuery();
...
}
_
firstJDBCTemplateQuery
は機能しますが、データベースへの接続を閉じます。 2番目のsecondJDBCTempolateQuery
が実行されたとき
_Java.sql.SQLException: Connection is closed exception
_
原因がスローされます
_org.springframework.transaction.TransactionSystemException: Could not roll back JPA transaction ...
_
私の構成:[〜#〜] edit [〜#〜]
_ <bean id="dataSource"
class="org.Apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="emf" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="emf"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="packagesToScan" value="com.emisoft.AMI.user.domain" />
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
<prop key="hibernate.max_fetch_depth">3</prop>
<prop key="hibernate.jdbc.fetch_size">50</prop>
<prop key="hibernate.jdbc.batch_size">10</prop>
<prop key="hibernate.show_sql">false</prop>
</props>
</property>
</bean>
<jpa:repositories base-package="com.emisoft.AMI.user.repository"
entity-manager-factory-ref="emf" transaction-manager-ref="transactionManager" />
...
_
'firstJDBCTemplateQuery'がdb接続を閉じる理由がわかりません。この問題を解決する方法は?
StackTrace:
_ org.springframework.jdbc.support.MetaDataAccessException: Error while extracting DatabaseMetaData; nested exception is Java.sql.SQLException: Connection is closed.
at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.Java:296)
at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.Java:320)
at org.springframework.jdbc.support.SQLErrorCodesFactory.getErrorCodes(SQLErrorCodesFactory.Java:214)
at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.setDataSource(SQLErrorCodeSQLExceptionTranslator.Java:140)
at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.<init>(SQLErrorCodeSQLExceptionTranslator.Java:103)
at org.springframework.jdbc.support.JdbcAccessor.getExceptionTranslator(JdbcAccessor.Java:99)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.Java:605)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.Java:639)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.Java:668)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.Java:676)
at org.springframework.jdbc.core.JdbcTemplate.queryForObject(JdbcTemplate.Java:731)
at org.springframework.jdbc.core.JdbcTemplate.queryForObject(JdbcTemplate.Java:747)
at org.springframework.jdbc.core.JdbcTemplate.queryForInt(JdbcTemplate.Java:782)
at org.springframework.security.provisioning.JdbcUserDetailsManager.findGroupId(JdbcUserDetailsManager.Java:373)
at org.springframework.security.provisioning.JdbcUserDetailsManager.addUserToGroup(JdbcUserDetailsManager.Java:301)
//////////////////////////////////////////////////This is secondJDBCTemplateQuery///////////
at com.emisoft.AMI.user.service.impl.UserServiceImpl.insert(UserServiceImpl.Java:42)
///////////////////////////////////////////////////////////////////////////////////////////
at Sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at Sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.Java:57)
at Sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.Java:43)
at Java.lang.reflect.Method.invoke(Method.Java:606)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.Java:317)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.Java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.Java:150)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.Java:96)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.Java:260)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.Java:94)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.Java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.Java:204)
at com.Sun.proxy.$Proxy46.insert(Unknown Source)
at com.kulig.test.service.PaymentServiceContext.main(PaymentServiceContext.Java:28)
Caused by: Java.sql.SQLException: Connection is closed.
at org.Apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.checkOpen(PoolingDataSource.Java:185)
at org.Apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.getMetaData(PoolingDataSource.Java:244)
at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.Java:285)
... 29 more
DEBUG: org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator - Unable to translate SQLException with Error code '0', will now try the fallback translator
DEBUG: org.springframework.orm.jpa.JpaTransactionManager - Initiating transaction rollback
DEBUG: org.springframework.orm.jpa.JpaTransactionManager - Rolling back JPA transaction on EntityManager [org.hibernate.ejb.EntityManagerImpl@76c741]
DEBUG: org.hibernate.engine.transaction.spi.AbstractTransactionImpl - rolling back
DEBUG: org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction - re-enabling autocommit
DEBUG: org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction - Could not toggle autocommit
Java.sql.SQLException: Connection is closed.
at org.Apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.checkOpen(PoolingDataSource.Java:185)
at org.Apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.setAutoCommit(PoolingDataSource.Java:327)
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.releaseManagedConnection(JdbcTransaction.Java:127)
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doRollback(JdbcTransaction.Java:170)
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.rollback(AbstractTransactionImpl.Java:209)
at org.hibernate.ejb.TransactionImpl.rollback(TransactionImpl.Java:106)
at org.springframework.orm.jpa.JpaTransactionManager.doRollback(JpaTransactionManager.Java:539)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback(AbstractPlatformTransactionManager.Java:846)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.rollback(AbstractPlatformTransactionManager.Java:823)
at org.springframework.transaction.interceptor.TransactionAspectSupport.completeTransactionAfterThrowing(TransactionAspectSupport.Java:493)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.Java:264)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.Java:94)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.Java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.Java:204)
at com.Sun.proxy.$Proxy46.insert(Unknown Source)
at com.kulig.test.service.PaymentServiceContext.main(PaymentServiceContext.Java:28)
DEBUG: org.springframework.orm.jpa.JpaTransactionManager - Closing JPA EntityManager [org.hibernate.ejb.EntityManagerImpl@76c741] after transaction
DEBUG: org.hibernate.engine.jdbc.internal.LogicalConnectionImpl - Releasing JDBC connection
DEBUG: org.hibernate.engine.jdbc.internal.LogicalConnectionImpl - Released JDBC connection
ERROR: org.springframework.transaction.interceptor.TransactionInterceptor - Application exception overridden by rollback exception
org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback; uncategorized SQLException for SQL [select id from groups where group_name = ?]; SQL state [null]; error code [0]; Connection is closed.; nested exception is Java.sql.SQLException: Connection is closed.
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.Java:83)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.Java:80)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.Java:80)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.Java:605)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.Java:639)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.Java:668)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.Java:676)
at org.springframework.jdbc.core.JdbcTemplate.queryForObject(JdbcTemplate.Java:731)
at org.springframework.jdbc.core.JdbcTemplate.queryForObject(JdbcTemplate.Java:747)
at org.springframework.jdbc.core.JdbcTemplate.queryForInt(JdbcTemplate.Java:782)
at org.springframework.security.provisioning.JdbcUserDetailsManager.findGroupId(JdbcUserDetailsManager.Java:373)
at org.springframework.security.provisioning.JdbcUserDetailsManager.addUserToGroup(JdbcUserDetailsManager.Java:301)
at com.emisoft.AMI.user.service.impl.UserServiceImpl.insert(UserServiceImpl.Java:42)
at Sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at Sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.Java:57)
at Sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.Java:43)
at Java.lang.reflect.Method.invoke(Method.Java:606)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.Java:317)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.Java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.Java:150)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.Java:96)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.Java:260)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.Java:94)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.Java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.Java:204)
at com.Sun.proxy.$Proxy46.insert(Unknown Source)
at com.kulig.test.service.PaymentServiceContext.main(PaymentServiceContext.Java:28)
Caused by: Java.sql.SQLException: Connection is closed.
at org.Apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.checkOpen(PoolingDataSource.Java:185)
at org.Apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.prepareStatement(PoolingDataSource.Java:312)
at org.springframework.jdbc.core.JdbcTemplate$SimplePreparedStatementCreator.createPreparedStatement(JdbcTemplate.Java:1446)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.Java:583)
... 23 more
Exception in thread "main" org.springframework.transaction.TransactionSystemException: Could not roll back JPA transaction; nested exception is javax.persistence.PersistenceException: unexpected error when rollbacking
at org.springframework.orm.jpa.JpaTransactionManager.doRollback(JpaTransactionManager.Java:543)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback(AbstractPlatformTransactionManager.Java:846)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.rollback(AbstractPlatformTransactionManager.Java:823)
at org.springframework.transaction.interceptor.TransactionAspectSupport.completeTransactionAfterThrowing(TransactionAspectSupport.Java:493)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.Java:264)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.Java:94)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.Java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.Java:204)
at com.Sun.proxy.$Proxy46.insert(Unknown Source)
at com.kulig.test.service.PaymentServiceContext.main(PaymentServiceContext.Java:28)
Caused by: javax.persistence.PersistenceException: unexpected error when rollbacking
at org.hibernate.ejb.TransactionImpl.rollback(TransactionImpl.Java:109)
at org.springframework.orm.jpa.JpaTransactionManager.doRollback(JpaTransactionManager.Java:539)
... 9 more
Caused by: org.hibernate.TransactionException: rollback failed
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.rollback(AbstractTransactionImpl.Java:215)
at org.hibernate.ejb.TransactionImpl.rollback(TransactionImpl.Java:106)
... 10 more
Caused by: org.hibernate.TransactionException: unable to rollback against JDBC connection
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doRollback(JdbcTransaction.Java:167)
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.rollback(AbstractTransactionImpl.Java:209)
... 11 more
Caused by: Java.sql.SQLException: Connection is closed.
at org.Apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.checkOpen(PoolingDataSource.Java:185)
at org.Apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.rollback(PoolingDataSource.Java:322)
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doRollback(JdbcTransaction.Java:163)
... 12 more
_
[〜#〜] edit [〜#〜]スタックトレースでsecondJDBCTemplateQuery
をチェックしました。
[〜#〜]編集[〜#〜]
私は_org.springframework.security.provisioning.JdbcUserDetailsManager
_を使用します
firstJDBCTemplateQuery
はcreateUser(UserDetails user)
です
secondJDBCTemplateQuery
はaddUserToGroup(String username, String groupName)
です
_public void createUser(final UserDetails user) {
validateUserDetails(user);
getJdbcTemplate().update(createUserSql, new PreparedStatementSetter() {
public void setValues(PreparedStatement ps) throws SQLException {
ps.setString(1, user.getUsername());
ps.setString(2, user.getPassword());
ps.setBoolean(3, user.isEnabled());
}
});
if (getEnableAuthorities()) {
insertUserAuthorities(user);
}
}
public void addUserToGroup(final String username, final String groupName) {
logger.debug("Adding user '" + username + "' to group '" + groupName + "'");
Assert.hasText(username);
Assert.hasText(groupName);
final int id = findGroupId(groupName);
getJdbcTemplate().update(insertGroupMemberSql, new PreparedStatementSetter() {
public void setValues(PreparedStatement ps) throws SQLException {
ps.setInt(1, id);
ps.setString(2, username);
}
});
userCache.removeUserFromCache(username);
}
_
デバッグ結果の編集:
起動時のBeiginトランザクションmyMethod()
:
_DEBUG: org.springframework.orm.jpa.JpaTransactionManager - Creating new transaction with name [com.emisoft.AMI.user.service.impl.UserServiceImpl.insert]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
DEBUG: org.springframework.orm.jpa.JpaTransactionManager - Opened new EntityManager [org.hibernate.ejb.EntityManagerImpl@b18ac9] for JPA transaction
DEBUG: org.hibernate.engine.transaction.spi.AbstractTransactionImpl - begin
DEBUG: org.hibernate.engine.jdbc.internal.LogicalConnectionImpl - Obtaining JDBC connection
DEBUG: org.hibernate.engine.jdbc.internal.LogicalConnectionImpl - Obtained JDBC connection
DEBUG: org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction - initial autocommit status: true
DEBUG: org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction - disabling autocommit
DEBUG: org.springframework.orm.jpa.JpaTransactionManager - Exposing JPA transaction as JDBC transaction [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@940dc4]
_
////////////////////////////////// firstJDBCTemplateMethod
:///////// /////////////////////////
_DEBUG: org.springframework.jdbc.core.JdbcTemplate - Executing prepared SQL update
DEBUG: org.springframework.jdbc.core.JdbcTemplate - Executing prepared SQL statement [insert into users (username, password, enabled) values (?,?,?)]
DEBUG: org.springframework.jdbc.core.JdbcTemplate - SQL update affected 1 rows
_
///////////////////////////////////////// secondJDBCTemplateMethod
:// //////////////////////////////////
_DEBUG: org.springframework.jdbc.core.JdbcTemplate - Executing prepared SQL query
DEBUG: org.springframework.jdbc.core.JdbcTemplate - Executing prepared SQL statement [select id from groups where group_name = ?]
INFO : org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [org/springframework/jdbc/support/sql-error-codes.xml]
INFO : org.springframework.jdbc.support.SQLErrorCodesFactory - SQLErrorCodes loaded: [DB2, Derby, H2, HSQL, Informix, MS-SQL, MySQL, Oracle, PostgreSQL, Sybase]
DEBUG: org.springframework.jdbc.support.SQLErrorCodesFactory - Looking up default SQLErrorCodes for DataSource [org.Apache.commons.dbcp.BasicDataSource@150f6f]
WARN : org.springframework.jdbc.support.SQLErrorCodesFactory - Error while extracting database product name - falling back to empty error codes
org.springframework.jdbc.support.MetaDataAccessException: Error while extracting DatabaseMetaData; nested exception is Java.sql.SQLException: Connection is closed. ///This is the beginning of stacktrace which is located above.
_
[〜#〜] edit [〜#〜]PaymentServiceContext
:
_public class PaymentServiceContext {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
"com/kulig/test/service/PaymentServiceTest-context.xml");
UserService userService = context.getBean(UserService.class);
///CREATE POJO OBJECTS credentials and p
...
userService.insert(credentials, p);
}
}
_
Hibernateにはバグがあると思います。私が変更され
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.2.5.Final</version>
</dependency>
に
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.1.12.Final</version>
</dependency>
そしてそれは動作します。
実際、私は最近同じ問題を抱えています...
Hibernateコードを介してデバッグした後、ある時点でHibernate4がHibernateJpaDialect.releaseConnectionを呼び出すことに気付きました。以前のコメントは、接続を解放するだけであり、トランザクションコンテキストによって使用される接続であるため、接続を閉じることではないことを示唆しています。ただし、そのreleaseConnectionメソッドは実際にはJdbcUtils.closeConnection(con)を呼び出します。責任のあるHibernateJpaDialectクラスは、実際には、休止状態ではなく、Springフレームワークの一部です。
最終的に、この問題はSpringによってバグ(SPR-10395)として報告されており、リリース3.2.3以降で修正する必要があります。したがって、最終的にはHibernate 4.2を使用できますが、その場合はSpring(orm)をアップグレードする必要があります。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>3.2.3</version>
</dependency>
春のオームアーティファクトからのHibernateJpaDialectの2つの異なるバージョンの比較。これを指摘してくれた@KevinChabotに感謝します。
HibernateJpaDialect(spring-orm ver 3.1.4)
public void releaseConnection(Connection con) {
JdbcUtils.closeConnection(con);
}
HibernateJpaDialect(spring-orm ver 3.2.8)
public void releaseConnection(Connection con) {
if (sessionConnectionMethod != null) {
// Need to explicitly call close() with Hibernate 3.x in order to allow
// for eager release of the underlying physical Connection if necessary.
// However, do not do this on Hibernate 4.2+ since it would return the
// physical Connection to the pool right away, making it unusable for
// further operations within the current transaction!
JdbcUtils.closeConnection(con);
}
}
spring-orm 3.2.3+
に切り替えると、この問題は解決します。 pom.xmlに明示的にspring-ormを含めるように注意してください。よくある間違いは、pom.xmlにspring-data
のみが含まれ、spring-orm
から推移的な依存関係を介してspring-data
をフェッチする場合です。これは、バージョンが間違っている可能性があります。
まず、JPAにDataSource
と同じJdbcTemplate
を使用していることを確認してください。次に、DataSource
をJpaTransactionManager
に配線します。
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="emf" />
<property name="dataSource" ref="dataSource" />
</bean>
これにより、トランザクションは同じトランザクションマネージャーによって管理されます(1つのトランザクションのみを管理する必要があります)