Spring JdbcTemplate查询关闭数据库连接

Spring JdbcTemplate查询关闭数据库连接,spring,hibernate,jpa,jdbctemplate,Spring,Hibernate,Jpa,Jdbctemplate,我在hibernate中使用jpa。我有以下方法: @Transactional public void myMethod(){ ... firstJDBCTemplateQuery(); secondJDBCTemplateQuery(); ... } firstJDBCTemplateQuery可以工作,但它会关闭到数据库的连接。执行第二个secondjdbtempoleQuery时 java.sql.SQLException:连接已关闭异常 是什么原因造成的 org.springfra

我在hibernate中使用jpa。我有以下方法:

@Transactional
public void myMethod(){
...
firstJDBCTemplateQuery();
secondJDBCTemplateQuery();
...

}
firstJDBCTemplateQuery
可以工作,但它会关闭到数据库的连接。执行第二个
secondjdbtempoleQuery

java.sql.SQLException:连接已关闭异常

是什么原因造成的

org.springframework.transaction.TransactionSystemException:无法回滚JPA事务…

我的配置: 编辑

     <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" />
        ...
编辑调试结果

Beigin事务启动时
myMethod()

//////////////////////////////////
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
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.
/////////////////////////////////////////
secondJDBCTemplateMethod
: ////////////////////////////////////

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
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.
编辑
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);

    }

}

首先,确保JPA使用的数据源与JdbcTemplate使用的数据源相同。接下来将
数据源连接到
JpaTransactionManager

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="emf" />
    <property name="dataSource" ref="dataSource" />        
</bean>


这将使事务由同一个事务管理器管理(您应该只有一个事务管理器)

我认为hibernate中存在错误。我更改了

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-entitymanager</artifactId>
    <version>4.2.5.Final</version>
</dependency>

org.hibernate
休眠实体管理器
4.2.5.最终版本


org.hibernate
休眠实体管理器
4.1.12.最终版本

事实上,我最近也遇到过同样的问题

在通过Hibernate代码进行调试之后,我注意到Hibernate 4在某个时候调用了HibernateJpaDialect.releaseConnection。之前的评论建议只释放连接,而不关闭连接,因为它是事务上下文使用的连接。然而,releaseConnection方法实际上调用了JdbcUtils.closeCon负责的HibernateAppDialect类实际上是spring框架的一部分,而不是hibernate

最后,Spring将此问题报告为一个bug(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>

org.springframework
春季甲虫
3.2.3

比较spring orm工件的两个不同版本的HibernateAppDialect。 感谢@Kevin Chabot指出这一点:

HibernatePadialect(spring orm版本3.1.4)

HibernatePadialect(spring orm版本3.2.8)


切换到
spring orm 3.2.3+
解决了这个问题。请注意在pom.xml中显式地包含spring orm。常见的错误是pom.xml只包含
spring数据
,并通过从
spring数据
中的传递依赖项获取
spring orm
,而不是错误的版本。

您能理解吗您能发布
firstJDBCTemplateQuery
secondJDBCTemplateQuery
code第一眼看到配置没有问题吗?您能发布第一个事务/周围方法的调试/跟踪信息吗?以及
PaymentServiceContext
的代码吗?我添加了。只调用
用户service.insert(..)
方法,我在我的帖子开头将其命名为
myMethod()
),我认为
org.springframework.orm.jpa.JpaTransactionManager
会自动找到数据源。我只有一个数据源,所以应该没有问题。我按照你说的做了,没有任何更改。只有当EntityManager使用的数据源相同时,才会检测到它。你能用你的完整配置更新你的问题吗(
persistence.xml
EntityManagerFactory
配置)。我添加了
EntityManagerFactory
。我使用
EntityManagerFactory
中的
packagesToScan
属性,而不是
persistence.xml
。升级spring应该允许您使用hibernate 4.2(见下文)
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-entitymanager</artifactId>
    <version>4.1.12.Final</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-orm</artifactId>
    <version>3.2.3</version>
</dependency>
public void releaseConnection(Connection con) {
    JdbcUtils.closeConnection(con);
}
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);
    }
}