在Java OOP样式

时间:2016-07-05 14:24:38

标签: java mysql oop heroku

我最近做了编程挑战。揭露用于管理虚构电影租赁公司的API是一次OOP挑战。我选择使用sparkjava,并使用heroku模板。 I have posted the code to Github here,并邀请任何人查询README文档中提供的网址。密码为secret

我收到了很多关于需要改进的事情的好反馈。一个反对意见是:

  

直接处理驱动程序的连接,无需任何处理   正确关闭连接。

所以我试图弄清楚这意味着什么,为什么会出现问题,以及如何修复它并使我的代码更好。

例如我有这个方法,in the main class

public static int validate_customer(String cust) throws SQLException, URISyntaxException {
    int customer = 0;
    try{
        customer = Integer.parseInt(cust);
    }catch (Exception e){
        throw new SQLException("Invalid customer integer -> " + cust);
    }

    Connection connection = DatabaseUrl.extract().getConnection();
    PreparedStatement stmt = connection.prepareStatement("SELECT count(*) from customers where id = ?;");
    stmt.setInt(1, customer);
    ResultSet rs = stmt.executeQuery();
    rs.next();
    if ( rs.getInt(1) < 1 ){
        throw new SQLException("Invalid customer id -> " + customer);
    }
    rs.close();
    stmt.close();
    return customer;
}

为什么这是处理与数据库交互的错误方法?主类中还有其他与DB交互的方法,但该技术与此示例基本相同。

对我来说,如果与数据库的连接出现问题,它将出现在行Connection connection = DatabaseUrl.extract().getConnection();中并抛出SQLException。如果某些事情发生在连接上,并且查询的某些部分不起作用,则会从此validate_customer方法抛出异常。为什么我的代码中存在这个问题?

3 个答案:

答案 0 :(得分:3)

  

直接通过驱动程序处理连接

这意味着您没有使用数据库连接池(如HikariCP),这意味着可能会很快耗尽您的连接限制。 Heroku示例不使用数据库连接池来限制示例中的依赖项。

  

没有正确关闭连接的任何处理。

这意味着stmt.close();不在finally块中,这意味着如果方法中抛出异常,stmt永远不会被关闭。

答案 1 :(得分:2)

我经常看到在try catch的finally块中完成连接的关闭。也许在try catch语句中处理方法内部的SQL异常会更好并关闭finally块中的资源。这正是我经常看到的。我希望它可能有所帮助。

为了更新这一点,Java 7引入了一个名为&#39; try-with-resources&#39;的功能。 这似乎是清理资源的新首选方式。 举个例子:

try(Connection connection = Connection.getConnection();
    PreparedStatement stmt = connection.prepareStatement("..."))
{
    ...
}

尝试使用资源会自动关闭实现 AutoClosable 接口的所有资源,并在try语句的括号中声明。

以下是官方教程文档的链接:https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html

答案 2 :(得分:1)

我建议您使用datasource。您是否在类路径中拥有数据源和jdbc数据库特定驱动程序的依赖项。在这种情况下,我使用dbcp2mysql

public long count(final int customerId) {

    int count;

    final String query = "SELECT count(*) FROM customers WHERE id = ?";

    try (final Connection conn = dataSource.getConnection();
         final PreparedStatement prepStatement = conn.prepareStatement(query)) {

        prepStatement.setInt(1, customerId);

        final ResultSet rs = prepStatement.executeQuery();

        rs.next();
        count = rs.getInt(1);

    } catch (SQLException e) {

        // You may want to log and throw a custom exception here.
        throw new RuntimeException(e);
    }

    return count;
}

public DataSource dataSource() {

    final org.apache.commons.dbcp2.BasicDataSource dataSource =
        new org.apache.commons.dbcp2.BasicDataSource();

    dataSource.setDriverClassName("com.mysql.jdbc.Driver");
    dataSource.setUrl(environment.getProperty("jdbc:mysql://localhost:3306/myDatabase"));
    dataSource.setUsername(environment.getProperty("root"));
    dataSource.setPassword(environment.getProperty("password"));

    return dataSource;
}

注意我没有明确关闭 finally 块上的连接,因为自Java 7以来 Connection PreparedStatement 是{{3 }}