Java EJB3.0托管bean注入和数据库连接关闭

Java EJB3.0托管bean注入和数据库连接关闭,java,jdbc,ejb-3.0,cdi,jboss6.x,Java,Jdbc,Ejb 3.0,Cdi,Jboss6.x,在EJB3.0JBoss6环境中,我有一个名为DBInterface的bean,它被注入到许多dao类中以执行sql查询。DBInterface bean将数据源作为字段变量注入。DBInterface bean中的所有方法都从注入的数据源获取数据库连接,并在处理db调用后关闭连接。在运行应用程序时,经过一段时间后,我收到一个sql异常,表示无法创建db连接。我正在关闭finally块中每个方法调用的连接。我在哪里出错?我在jboss中使用EJB3.0。 当做 五 您应该使用try-catch块

在EJB3.0JBoss6环境中,我有一个名为DBInterface的bean,它被注入到许多dao类中以执行sql查询。DBInterface bean将数据源作为字段变量注入。DBInterface bean中的所有方法都从注入的数据源获取数据库连接,并在处理db调用后关闭连接。在运行应用程序时,经过一段时间后,我收到一个sql异常,表示无法创建db连接。我正在关闭finally块中每个方法调用的连接。我在哪里出错?我在jboss中使用EJB3.0。 当做 五


您应该使用try-catch块来关闭任何资源

if (rs != null) {
    rs.close();
}
if (st != null) {
    st.close();
}
if (con != null) {
    con.close();
}
应替换为:

if (rs != null) {
    try {
        rs.close();
    } catch (Exception exception) {
        logger.log("Failed to close ResultSet", exception);
    }
}
if (st != null) {
    try {
        st.close();
    } catch (Exception exception) {
        logger.log("Failed to close Statement", exception);
    }
}
if (con != null) {
    try {
        con.close();
    } catch (Exception exception) {
        logger.log("Failed to close Connection", exception);
    }
}
可以使用AbstractDAO类将其重构为更易于阅读的内容:

public class DAOException extends RuntimeException {
    public DAOException(Throwable cause) {
        super(cause);
    }
}

public abstract class AbstractDAO {
    private static Logger logger = ...;
    private DataSource dataSource;

    protected void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    public Connection getConnection() {
        try {
            return dataSource.getConnection();
        } catch (SQLException exception) {
            // There's nothing we can do
            throw new DAOException(exception);
        }
    }

    public void close(Connection connection) {
        try {
            connection.close();
        } catch (Exception exception) {
            // Log the exception
            logger.log("Failed to close Connection", exception);
        }
    }

    public void close(Statement statement) {
        try {
            statement.close();
        } catch (Exception exception) {
            // Log the exception
            logger.log("Failed to close Statement", exception);
        }
    }

    public void close(ResultSet resultSet) {
        try {
            resultSet.close();
        } catch (Exception exception) {
            // Log the exception
            logger.log("Failed to close ResultSet", exception);
        }
    }
}

public class MyDAO extends AbstractDAO {
    @Override
    @Resource("jdbc/myDS")
    protected void setDataSource(DataSource dataSource) {
        super.setDataSource(dataSource);
    }

    public void insert(MyObject myObject) {
        Connection connection = getConnection();
        try {
            PreparedStatement query = connection.createPreparedStatement("INSERT INTO MYOBJECT (ID, VALUE) VALUES (?, ?)");
            try {
                query.setLong(1, myObject.getID());
                query.setString(2, myObject.getValue());
                if (query.executeUpdate() != 1) {
                    throw new DAOException("ExecuteUpdate did not return expected result");
                }
            } finally {
                close(query);
            }
        } catch (SQLException exception) {
            // There's nothing we can do
            throw new DAOException(exception);
        } finally {
            close(connection);
        }
    }
}

我想知道的是你为什么不使用JPA?我会考虑只在性能关键的应用程序中使用JDBC,而这些应用程序不会从缓存中获益。

不要将数据源注入静态字段…还要确保在单独的try-catch块中关闭资源。如果你是对的,我不再将静态用于数据源。对不起,我把旧的测试代码粘贴在这里了。你所说的独立试捕块是什么意思?我在这段代码中没有看到任何其他错误?我将把它作为一个答案发布,因为我不能在这里发布代码。我不使用JPA的原因是由于第三方定期更新数据的复杂性。所以我需要在JPA帮不了我的几个地方使用查询,我可能会使用视图,而不是每次表结构改变时更新sql查询。
public class DAOException extends RuntimeException {
    public DAOException(Throwable cause) {
        super(cause);
    }
}

public abstract class AbstractDAO {
    private static Logger logger = ...;
    private DataSource dataSource;

    protected void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    public Connection getConnection() {
        try {
            return dataSource.getConnection();
        } catch (SQLException exception) {
            // There's nothing we can do
            throw new DAOException(exception);
        }
    }

    public void close(Connection connection) {
        try {
            connection.close();
        } catch (Exception exception) {
            // Log the exception
            logger.log("Failed to close Connection", exception);
        }
    }

    public void close(Statement statement) {
        try {
            statement.close();
        } catch (Exception exception) {
            // Log the exception
            logger.log("Failed to close Statement", exception);
        }
    }

    public void close(ResultSet resultSet) {
        try {
            resultSet.close();
        } catch (Exception exception) {
            // Log the exception
            logger.log("Failed to close ResultSet", exception);
        }
    }
}

public class MyDAO extends AbstractDAO {
    @Override
    @Resource("jdbc/myDS")
    protected void setDataSource(DataSource dataSource) {
        super.setDataSource(dataSource);
    }

    public void insert(MyObject myObject) {
        Connection connection = getConnection();
        try {
            PreparedStatement query = connection.createPreparedStatement("INSERT INTO MYOBJECT (ID, VALUE) VALUES (?, ?)");
            try {
                query.setLong(1, myObject.getID());
                query.setString(2, myObject.getValue());
                if (query.executeUpdate() != 1) {
                    throw new DAOException("ExecuteUpdate did not return expected result");
                }
            } finally {
                close(query);
            }
        } catch (SQLException exception) {
            // There's nothing we can do
            throw new DAOException(exception);
        } finally {
            close(connection);
        }
    }
}