Java链接sql:垃圾回收的陷阱

来源:互联网 发布:监控工程宝软件 编辑:程序博客网 时间:2024/06/08 07:37

最近在写微信平台的后台,在链接sql的时候出现问题,在不同的时间,进行查询操作,有时不能sql报错,有时运行正常。

查找原因,是因为我将sql查询的相关逻辑写在了sql类中,而对于jdbc的connection,PreparedStatement等资源,没有在函数中关闭释放,而是写了个finally方法,在finally方法中释放,但是,由于java垃圾回收机制,其垃圾回收的时间不定,即使在代码中显式执行垃圾回收的指令。因此,这个bug是因为java未进行垃圾回收,未执行finally方法,导致connection等资源没有释放,导致sql查询的失败。

下面贴一段修改bug后的代码,这个类对sql操作进行了封装,直接调用相应函数即可。

代码如下:

</pre><pre name="code" class="java">import java.sql.*;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;/** * Created by wangjian on 16-5-20. */public class DataBaseOperation {    final static String driverName = "com.mysql.jdbc.Driver"; //驱动名称    static final String DBUser = "********"; //mysql用户名    static final String DBPasswd = "******"; //mysql密码    static final String DBName = "*******"; //数据库名    static final String MySQLServer = "********"; //数据库名    static final String MySQLServerPort = "****"; //数据库名    public static List<Map<String,Object>> queryDB(String sql){        Connection conn=null;        PreparedStatement preparedStatement = null;        ResultSet resultSet = null;        List<Map<String,Object>> resultList = new ArrayList<Map<String, Object>>();        String url = "jdbc:mysql://sqld.duapp.com:4050/gLqNBKGAHFWicVlogCWf";        try{            Class.forName(driverName);            conn = DriverManager.getConnection(url,DBUser,DBPasswd);            preparedStatement = conn.prepareStatement(sql);            preparedStatement.execute();            resultSet = preparedStatement.getResultSet();            ResultSetMetaData resultSetMetaData = resultSet.getMetaData();            while(resultSet.next()){                Map<String,Object> column = new HashMap<String, Object>();                for(int i=1;i<=resultSetMetaData.getColumnCount();i++){                    column.put(resultSetMetaData.getColumnName(i),resultSet.getObject(i));                }                if(column.size()!=0)                    resultList.add(column);            }        }catch (Exception e){            e.printStackTrace();        }finally {            try{                preparedStatement.close();                conn.close();            }catch (Exception e){                e.printStackTrace();            }        }        return resultList;    }    public static void updateDB(String sql){        Connection conn=null;        PreparedStatement preparedStatement = null;        String url = "jdbc:mysql://"+MySQLServer+":"+MySQLServerPort+"/" + DBName;        try{            Class.forName(driverName);            conn = DriverManager.getConnection(url,DBUser,DBPasswd);            preparedStatement = conn.prepareStatement(sql);            preparedStatement.executeUpdate();        }catch (Exception e){            e.printStackTrace();        }finally {            try{                preparedStatement.close();                conn.close();            }catch (Exception e){                e.printStackTrace();            }        }    }    public static void insertDB(String sql){        updateDB(sql);    }    public static void deleteDB(String sql){        updateDB(sql);    }}



接下来,对这个类需要进行改进:1、防sql注入 2、相关数据库的用户名,密码等信息分离到xml文件中。

0 0