有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Tomcat 5.5 DBCP连接池数据源已关闭

我正在用Spring数据JPA和Hibernate开发一个Spring web应用程序,运行在Tomcat 5.5上。Tomcat使用DBCP进行连接池

池的定义如下:

<Resource auth="Container" driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver"
        factory="org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory"
        logAbandoned="true" maxActive="100" maxIdle="30" maxWait="10000"
        minIdle="3" name="..." password="..." removeAbandoned="true"
        type="javax.sql.DataSource"
        url="..." username="..." validationQuery="select 1" />

在Java端,我通过JNDI获取数据源,Spring将对象作为Singleton进行管理,它将只用于创建 整个管理工厂

现在是我的问题。当我第一次在刚启动的Tomcat上部署应用程序时,一切都很好。如果我第一次热部署应用程序,一切仍然正常。但如果我第二次热部署,会出现以下异常:

java.sql.SQLException: Data source is closed
at org.apache.tomcat.dbcp.dbcp.BasicDataSource.createDataSource(BasicDataSource.java:1362)
at org.apache.tomcat.dbcp.dbcp.BasicDataSource.getConnection(BasicDataSource.java:1044)

任何想法都将不胜感激,谢谢

更新:我在Tomcat 7.0.12上试过,它在我的机器上随处可见,也有同样的问题。我已经从commons dbcp切换到Tomcat JDBC连接池,问题在Tomcat 5.5和Tomcat 7上都解决了。现在在我看来,commons dbcp中有一个bug,或者Spring对它不友好?有人知道更多吗


共 (3) 个答案

  1. # 1 楼答案

    为数据源Springbean定义一个空方法。在取消部署时,如果没有定义destroyMethod,Spring会在bean上调用close()shutdown()。 看这个Why does Datasources close on Tomcat 7 undeploy with Spring Boot

    data.xml

    <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean" destroy-method="">
    

    或者在@Bean注释中

    @Bean(name = "dataSource", destroyMethod = "")
    public DataSource getDataSource() {...}
    
  2. # 2 楼答案

    首先,使用受支持的Tomcat版本。Commons DBCP已过时。您应该使用Tomca JDBC池或Commons DBCP2

  3. # 3 楼答案

    在新版Tomcat中,数据源实现了自动关闭。默认情况下,Spring会检测该接口,并在取消部署时调用数据源上的close。在一些有缺陷的Spring版本(4.1.x和<;4.2.2)中,如果检测到自动关闭接口,则会忽略destroyMethod

    另一种避免这种情况的方法是包装数据源

        @Bean
    public DataSource getJndiDataSource() {
        try {
            JndiTemplate jndiTemplate = new JndiTemplate();
            DataSource ds = (DataSource) jndiTemplate.lookup("java:comp/env/"+JNDI_DATASOURCE);
            return new DelegatingDataSource(ds);
        } catch(NamingException e){
            LOG.error("Could not find JNDI data source (java:comp/env/):"+JNDI_DATASOURCE, e);
            return null;
        }
    }
    

    通过使用DelegatingDataSource包装数据源,AutoClosable接口不会暴露于上下文,因此数据源不会关闭