Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java SQL连接悬空:哪里没有正确关闭连接?_Java_Mysql_Connection_Try With Resources - Fatal编程技术网

Java SQL连接悬空:哪里没有正确关闭连接?

Java SQL连接悬空:哪里没有正确关闭连接?,java,mysql,connection,try-with-resources,Java,Mysql,Connection,Try With Resources,我正在构建一个基本的java应用程序,将一些文件加载到mysql数据库中。我能够加载文件并填充我的表,没有任何问题。然而,在与审阅我的代码的人交谈之后,我显然没有正确地关闭连接并浪费资源。我在哪里不关闭连接?我做得不对吗 我在我的DbSinger类中使用try with resources构造来执行数据库的准备语句,只要实现了可自动关闭的接口,该接口就会自动关闭连接,而该接口位于Db的父类中。但是,永远不会到达close()方法。DbSinger在my main()中实例化,然后使用Singer

我正在构建一个基本的java应用程序,将一些文件加载到mysql数据库中。我能够加载文件并填充我的表,没有任何问题。然而,在与审阅我的代码的人交谈之后,我显然没有正确地关闭连接并浪费资源。我在哪里不关闭连接?我做得不对吗

我在我的DbSinger类中使用try with resources构造来执行数据库的准备语句,只要实现了可自动关闭的接口,该接口就会自动关闭连接,而该接口位于Db的父类中。但是,永远不会到达close()方法。DbSinger在my main()中实例化,然后使用Singer对象的数组列表运行它的单个方法populateSingers()

连接类

public class SQLConnection {
    private static final String servername = "localhost";
    private static final int port = 3306;
    private static final String user = "ng_user";
    private static final String pass = "ng";
    private static final String db = "ng_music";
    private static final String connectionString = "jdbc:mysql://" + servername + ":" + port + "/" + db;

    public Connection provide() {
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");

            return DriverManager.getConnection(connectionString, user, pass);

        }
        catch (SQLException | ClassNotFoundException e) {
            throw new SQLConnectionException(e);
        }
    }

    public class SQLConnectionException extends RuntimeException {
        SQLConnectionException(Exception e) {super(e);}
    }
}
public abstract class Db implements AutoCloseable{
    private Connection connection;

    Db() {
        SQLConnection sqlC = new SQLConnection();
        this.connection = sqlC.provide();
    }

    @Override
    public synchronized void close() throws SQLException {
        if(connection != null) {
            connection.close();
            connection = null;
            System.out.println("Connection closed");
        }
    }
    Connection getConnection() {
        return connection;

    }
    boolean checkIfPopulated(String query){
        try {
            PreparedStatement ps = getConnection().prepareStatement(query);
            ResultSet rs = ps.executeQuery();
            return !rs.next();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return true;
    }
}
抽象父类

public class SQLConnection {
    private static final String servername = "localhost";
    private static final int port = 3306;
    private static final String user = "ng_user";
    private static final String pass = "ng";
    private static final String db = "ng_music";
    private static final String connectionString = "jdbc:mysql://" + servername + ":" + port + "/" + db;

    public Connection provide() {
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");

            return DriverManager.getConnection(connectionString, user, pass);

        }
        catch (SQLException | ClassNotFoundException e) {
            throw new SQLConnectionException(e);
        }
    }

    public class SQLConnectionException extends RuntimeException {
        SQLConnectionException(Exception e) {super(e);}
    }
}
public abstract class Db implements AutoCloseable{
    private Connection connection;

    Db() {
        SQLConnection sqlC = new SQLConnection();
        this.connection = sqlC.provide();
    }

    @Override
    public synchronized void close() throws SQLException {
        if(connection != null) {
            connection.close();
            connection = null;
            System.out.println("Connection closed");
        }
    }
    Connection getConnection() {
        return connection;

    }
    boolean checkIfPopulated(String query){
        try {
            PreparedStatement ps = getConnection().prepareStatement(query);
            ResultSet rs = ps.executeQuery();
            return !rs.next();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return true;
    }
}
执行singers表数据库查询的具体类

public class DbSinger extends Db {
    public DbSinger() {
        super();
    }

    public void populateSingers(ArrayList<Singer> singers) {
        String populateSingersQuery = "insert into ng_singers(name, dob, sex) values(?,?,?)";
        if(!checkIfPopulated("select * from ng_singers")){
            System.out.println("Singer Table is already populated");
            return;
        }
        try (PreparedStatement ps = getConnection().prepareStatement(populateSingersQuery)) {
            for (Singer s : singers) {
                ps.setString(1, s.getName());
                ps.setDate(2, java.sql.Date.valueOf(s.getDob()));
                ps.setString(3, s.getSex());
                ps.addBatch();
            }
            ps.executeBatch();
            System.out.println("Singers added to table");
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

}
公共类DbSinger扩展数据库{
公共数据库(){
超级();
}
公共空间流行歌手(ArrayList歌手){
String populateSingersQuery=“插入ng_歌手(姓名、出生日期、性别)值(?,?)”;
如果(!checkIfPopulated(“从ng_歌手中选择*)){
System.out.println(“Singer表已填充”);
返回;
}
try(PreparedStatement ps=getConnection().prepareStatement(PopulateSingerQuery)){
(歌手s:歌手){
ps.setString(1,s.getName());
ps.setDate(2,java.sql.Date.valueOf(s.getDob());
ps.setString(3,s.getSex());
ps.addBatch();
}
ps.executeBatch();
System.out.println(“添加到表中的歌手”);
}捕获(SQLE异常){
e、 printStackTrace();
}
}
}

我的代码能够执行,能够正常运行,并且做它需要做的事情,但是我想了解我为什么不关闭连接,在哪里不关闭连接,以及如何解决这个问题。或者至少要理解我的做法是否有误。

您的代码已经过时了。您确实需要手动关闭。但是,在Java 8中,您可以使用
try with resource
如下所示

try(Connection conn=ds.getConnection();
语句stmt=conn.createStatement()){
试一试{
stmt.execute(dropsql);
}catch(异常忽略){}//ignore if表未删除
stmt.execute(createsql);
stmt.execute(insertsql);
try(ResultSet rs=stmt.executeQuery(selectsql)){
rs.next();
}捕获(异常e2){
e2.printStackTrace();
返回(“失败”);
}
}捕获(例外e){
e、 printStackTrace();
返回(“失败”);
}

您的代码是旧的。您确实需要手动关闭。但是,在Java 8中,您可以使用
try with resource
如下所示

try(Connection conn=ds.getConnection();
语句stmt=conn.createStatement()){
试一试{
stmt.execute(dropsql);
}catch(异常忽略){}//ignore if表未删除
stmt.execute(createsql);
stmt.execute(insertsql);
try(ResultSet rs=stmt.executeQuery(selectsql)){
rs.next();
}捕获(异常e2){
e2.printStackTrace();
返回(“失败”);
}
}捕获(例外e){
e、 printStackTrace();
返回(“失败”);
}

在您的例子中,您需要在
try with resources
语句中实例化DBSinger类以关闭底层连接

而不是做:

DbSinger dbSinger = new DbSinger();
您需要执行以下操作:

try (DbSinger dbSinger = new DbSinger()) {
// Your other code
}
这样,将自动调用在
Db
类中重写的
close()
方法

另外,通过以下方法关闭在
checkIfPopulated
方法中创建的
preparedStatement

try (PreparedStatement ps = getConnection().prepareStatement(query)) {
// Other codes
}

在您的情况下,需要在
try with resources
语句中实例化DBSinger类以关闭底层连接

而不是做:

DbSinger dbSinger = new DbSinger();
您需要执行以下操作:

try (DbSinger dbSinger = new DbSinger()) {
// Your other code
}
这样,将自动调用在
Db
类中重写的
close()
方法

另外,通过以下方法关闭在
checkIfPopulated
方法中创建的
preparedStatement

try (PreparedStatement ps = getConnection().prepareStatement(query)) {
// Other codes
}

请显示实例化的代码
DbSinger
。另外,您没有在
checkIfPopulated
method中关闭
PreparedStatement
publicstaticvoidmain(String[]args){start();}publicstaticvoidstart(){DAO DAO=new DAO();DbSinger DbSinger=new DbSinger();DbSinger.populateSingers(DAO.loadSingers(“data/ng_singers.txt”);}
DAO类和DAO.loadSingers只返回Singer对象的数组列表。我想通过使用try-with-resources,我不需要每次都关闭连接?如果不是这样的话,我会手动关闭它们。把代码放到你的问题中,看看我的答案。请展示实例化
DbSinger
的代码。另外,您没有在
checkIfPopulated
method中关闭
PreparedStatement
publicstaticvoidmain(String[]args){start();}publicstaticvoidstart(){DAO DAO=new DAO();DbSinger DbSinger=new DbSinger();DbSinger.populateSingers(DAO.loadSingers(“data/ng_singers.txt”);}
DAO类和DAO.loadSingers只返回Singer对象的数组列表。我想通过使用try-with-resources,我不需要每次都关闭连接?如果不是这样的话,我会手动关闭它们。把代码放在你的问题中,看看我的答案。谢谢你的回答!如果我不太理解,请原谅,但我不明白你的例子有多大区别