可以在多个类方法中使用相同的BasicDataSource,Connection,Statement和ResultSet对象吗??

时间:2019-03-06 12:36:23

标签: java maven debugging garbage-collection apache-commons-dbcp

我有下面的代码,该代码使用BasicDataSource,Sql Connection,Statement和ResultSet的静态对象。下面的代码工作正常,但是我只想知道使用这种编码实践的安全性。或如何优化以下代码,使其变得更稳定,更可靠。

public class Testing {
     static BasicDataSource bds = DBConnection.getInstance().getBds();
     static Connection con = null;
     static PreparedStatement stmt = null;
     static ResultSet rs = null;

    private void show() {
        try {
            con = bds.getConnection();
            stmt = con.prepareStatement("SELECT * FROM users");
            rs = stmt.executeQuery();
            if(rs.next()) {
                System.out.println(rs.getString("firstname") + " " + rs.getString("lastname"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            try {
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    private void display() {
        try {
            con = bds.getConnection();
            stmt = con.prepareStatement("SELECT * FROM agent_cities");
            rs = stmt.executeQuery();
            while(rs.next()) {
                System.out.println(rs.getString("city_name"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            try {
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    private void add() {
        try {
            con = bds.getConnection();
            stmt = con.prepareStatement("UPDATE users SET firstname = 'shsh' WHERE id = 2");
            stmt.executeUpdate();
            System.out.println("updated successfully");
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            try {
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args) {
        Testing t = new Testing();
        t.show();
        t.display();
        t.add();
    }
}

先谢谢了。 请分享您可以打破上述代码的案例,并对其安全性提出疑问。

更新: 仅更新以确保没有人可以使用我在上面的程序中使用的静态字段,因为上面的程序在部署到开发服务器上时包含错误。

在大型系统上使用上述代码后,我发现了该错误。一个月前,我对上面的代码没有任何问题,并且工作正常,但是今天我发现了该错误。

错误:

在击中我的API 6至7次后,它在第8次击中时停止给出响应。我真的不知道为什么,也不知道程序中存在漏洞。 但是现在,当我接受答案时,我更改了源代码,并开始在代码中使用尝试资源并删除了静态字段。

但是我仍然很想知道我在以上代码中发现的错误。 无法响应并在7-8 API命中后挂起。 请分享您对此的想法。我正在使用apache Tomcat 8.5.32服务器。 预先感谢。

3 个答案:

答案 0 :(得分:1)

如果我们谈论这样一个小程序,则或多或少可以。 但是不需要将con,stmt和rs保留为静态变量,可以在方法内部声明它们。另外,您需要重写try catch catch块并正确关闭资源:

    <?php


$con1 = mysqli_connect($con1_host, $con1_user, $con1_pass, $con1_bbdd);
$con2 = mysqli_connect($con2_host, $con2_user, $con2_pass, $con2_bbdd);

function get_records_sql($sql, $con) {
    $ret = array();
    if ($results = $con->query($sql)) {
        while ($row = $results->fetch_array()) {
            $ret []= $row;
        }
        $results->close();
    }
    return $ret;
}

// Get records from foo_bar connection1
$records = get_records_sql("SELECT * FROM foo_bar", $con1);

foreach ($records as $record) {
    // Inserting records to foo_bar connection2
    $sql = "INSERT INTO foo_bar (`name `, `data`, `timecreated`) VALUES ('{$record['name']}', '{$record['data']}', '{$record['timecreated']}')";
    mysqli_query($con2, $sql);
    $id = mysqli_insert_id($con);
}

下一步,您可以检查try-with-resources的构造以清除此代码。

答案 1 :(得分:1)

最好使用尝试使用资源。即使在引发异常或内部返回时,这也会自动关闭Connection,Statement和ResultSet。

    String sql = "UPDATE users SET firstname = ? WHERE id = ?";
    try (Connection con = bds.getConnection();
            PreparedStatement stmt = con.prepareStatement()) {
        stmt.setString(1, "shsh");
        stmt.setLong(2, 2);
        stmt.executeUpdate();
        System.out.println("updated successfully");
    }

    String sql = "SELECT city_name FROM agent_cities";
    try (Connection con = bds.getConnection();
            PreparedStatement stmt = con.prepareStatement()) {
        try (ResultSet rs = stmt.executeQuery()) {
            while(rs.next()) {
                System.out.println(rs.getString("city_name"));
            }
        }
    }

这对于垃圾收集更好。防止rs2,rs3异常。允许多用户并发,例如在服务器应用程序中。自行查询。 static的风格甚至更像是全局变量。

答案 2 :(得分:1)

您应该使用try-with-resources以避免任何类型的连接泄漏。

下面的示例从文件中读取第一行。它使用BufferedReader的实例从文件中读取数据。 BufferedReader是一种资源,程序完成后必须将其关闭:

static String readFirstLineFromFile(String path) throws IOException {
    try (BufferedReader br =
                   new BufferedReader(new FileReader(path))) {
        return br.readLine();
    }
}