首页 > 解决方案 > Wildfly 20 中未关闭数据源池连接

问题描述

我有一个运行 MariaDB 数据库的 Wildfly Java 应用程序。最初连接工作正常,但在 20 个连接(默认值)之后,它下次尝试连接服务器时挂起,大约一分钟后它会抛出以下异常:

javax.resource.ResourceException: IJ000453: Unable to get managed connection for java:jboss/datasources/IndustryDS

这就是我连接和关闭数据源的方式:

    private InitialContext context = null;
    private DataSource ds = null;
    private Connection conn = null;

    try {
        context = new InitialContext();
        ds = (DataSource)context.lookup(pool);
        conn = ds.getConnection();           // <--- here is where it hangs 
        
        // use the connection


        if (conn != null)
            conn.close();

        if (context != null)
            context.close();

    } 
    catch (NamingException e) {
        logger.error(e.getMessage());
        throw new DAOException(e.getMessage());
    } 
    catch (SQLException e) {
        logger.error(e.getMessage());
        throw new DAOException(e.getMessage());  // <--- this error is thrown
    }

Standalone.xml 中的数据源配置

            <datasource jta="true" jndi-name="java:jboss/datasources/IndustryDS" 
                        pool-name="IndustryDS" enabled="true" use-java-context="true">
                <connection-url>jdbc:mariadb://localhost:3306/industry</connection-url>
                <driver>mariadb</driver>
                <security>
                    <user-name>user</user-name>
                    <password>xxxxxx/password>
                </security>
            </datasource>

默认情况下,MariaDB 支持 150 个连接,因此数据库应该不是问题。Wildfly 中默认的最大池大小为 20,我是系统中唯一的用户。每次我在我的应用程序中启动一个功能时,我都会请求两个连接,然后断开连接。

为什么即使我关闭数据源连接也不可用?

标签: javajbosswildflyjava-ee-8

解决方案


您的代码的一个问题是,如果出现异常,上下文和连接可能不会关闭。

解决这个问题的旧方法是在一个finally块中关闭资源。现代的方法是使用try with resources。例如:

try (InitialContext context = new InitialContext();
     Connection conn = ((DataSource) context.lookup(pool)).getConnection()) {
    // use the connection
} catch (NamingException e) {
    logger.error(e.getMessage());
    throw new DAOException(e.getMessage());
} catch (SQLException e) {
    logger.error(e.getMessage());
    throw new DAOException(e.getMessage()); 
}

资源尝试从资源声明开始,其中资源被声明和初始化。然后是一个使用资源的机构。最后你有(可选的)catchfinally块。

秘诀在于try with resources构造将自动关闭每个(非空)资源,其顺序与打开它们的顺序相反。关闭调用引发的异常将得到适当处理。等等。

(你可以(或多或少)用旧的方式用finally块实现同样的事情,但它很复杂。)


推荐阅读