100分请java或jsp高手来优化我的DB.java数据库操作代码!代码如下(DB.java)
package daima;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class DB {
    
    /** Creates a new instance of DB */
    public DB() {
    }
    Connection conn=null;
    /**
     *加载sqlserver驱动程序
     */
    private void loadMSsqlDriver()
    {
        try {
            Class.forName("org.logicalcobwebs.proxool.ProxoolDriver");
            conn = DriverManager.getConnection("proxool.myoracle");
        } catch (SQLException ex) {
            ex.printStackTrace();
        } catch (ClassNotFoundException ex) {
            ex.printStackTrace();
        }
    }
    /**
     *处理sqlServer数据库的查询操作,
     *传进去一查询语句,返回一个ResultSet结果集
     */
    public ResultSet MSquery(String querySql)
    {     
        this.loadMSsqlDriver();
        ResultSet rs=null;
        try {
            Statement stmt=conn.createStatement();
            rs=stmt.executeQuery(querySql);
        } catch (SQLException ex) {
            ex.printStackTrace();
        } 
    
         return rs;
    }
    /**
     *处理sqlServer数据库 增 删 改 操作
     *会返回一个boolean值,true执行成功,false执行失败
     */
    public boolean MSupdate(String updateSql)
    {
        this.loadMSsqlDriver();
        boolean check=false;
        int i=0;
        try {
            Statement stmt=conn.createStatement();
            i = stmt.executeUpdate(updateSql);
        } catch (SQLException ex) {
            ex.printStackTrace();
        }
        if(i!=0)
            check=true;
        this.close();
        return check;
    }
    /**
     *关闭连接,将连接重新放回到池中
     */
    public void close()
    {
        try {
            if(conn!=null)
            this.conn.close();
        } catch (SQLException ex) {
            ex.printStackTrace();
        }
    }
    
}问题主要为下面代码
 
 public ResultSet MSquery(String querySql)
    {     
        this.loadMSsqlDriver();
        ResultSet rs=null;
        try {
            Statement stmt=conn.createStatement();
            rs=stmt.executeQuery(querySql);
        } catch (SQLException ex) {
            ex.printStackTrace();
        } 
    
         return rs;
    }
主要问题为:当我用this.loadMSsqlDriver()方法来调用和建立数据库连接时,当我每刷新一次,它就被调用一次,那么conn也就被创建一次。因conn.close()每次没有关闭
这样重复刷新,数据库连接很快不够用了,然后就拿不到链接了,然后就 conn = null 了,最好导致页面刷新几次经常出现java.lang.NullPointerException.

请高手来优化我的上面代码,使this.loadMSsqlDriver()一次就conn.close(),或者不用this.loadMSsqlDriver()方法了来改进一下!
小弟初学者,万分感谢!

解决方案 »

  1.   

     public ResultSet MSquery(String querySql)
        {     
            this.loadMSsqlDriver();
            ResultSet rs=null;
            try {
                Statement stmt=conn.createStatement();
                rs=stmt.executeQuery(querySql);
            } catch (SQLException ex) {
                ex.printStackTrace();
            } finally {
                if (rs != null) rs.close();
                if (conn != null) conn.close();
            }
                
             return rs;
        }
      

  2.   

    sorry 刚才没看清楚你的代码,你为什么要返回ResultSet呢,这样写跟别的层的耦合就大了,不太好
      

  3.   

    楼上的改法不行,不仅编译出错,即使编译不出错jsp页面调用后也出错的
      

  4.   

    提示:
    专家说我的代码逻辑有问题,那个  
    loadMSsqlDriver 不应该在这里调用,而应该是类似这样的 loadMSsqlDriver(); // 获取连接 
    MSquery(sql);  // 执行查询 
    。。 // 其他的操作 
    close();  // 关闭连接 我改了几次没改好,小弟水平有限,请高手指点并改正!
      

  5.   

    修改loadMSsqlDriver();
    public Connection loadMSsqlDriver(){Connection connection = null;
    try {
                Class.forName("org.logicalcobwebs.proxool.ProxoolDriver");
                conn = DriverManager.getConnection("proxool.myoracle");
            } catch (SQLException ex) {
                ex.printStackTrace();
            } catch (ClassNotFoundException ex) {
                ex.printStackTrace();
            }
    return connection ;
    }
      

  6.   

    可以参考一下我BLOG的这篇文章,也许对你有用
    http://blog.csdn.net/AXuan_Good_GAME/archive/2008/04/04/2250607.aspx
      

  7.   

    在别的地方使用返回的ResultSet之后调用以下DB.close()如何?在执行数据库操作的地方应该能跟踪数据库连接,以便及时关闭释放资源
      

  8.   

    返回的ResultSet之后调用以下DB.close(),不行的
      

  9.   

    /*
     * 数据库连接工具类
     * 说明:DBToolsX-此工具类用于获取数据库连接与关闭数据库连接,关闭结果集等功能。
     * 无需实例化该工具类(DBToolsX),可直接调用此工具类(DBToolsX)的静态方法
     * 注意:1.使用前请导入相应适当的Jar文件
     *      2.注意更改为适用的加载数据库驱动
     *      3.注意更改为适用的数据库连接字符串(URL)
     *      4.注意更改为正确的数据库用户名(USER)和密码(PWD)
     *      5.请注意检查加载数据库驱动与数据库连接字符串(URL)是否合适,正确
     */
    import java.sql.*;public class DBToolsX 
    ...{
     //静态块:加载数据库驱动
     static
     ...{
      try 
      ...{
       Class.forName("");
       //加载SQlServer2000驱动-com.microsoft.jdbc.sqlserver.SQLServerDriver
       //加载MySQL5.x驱动-com.mysql.jdbc.Driver
       //加载Oracle9i驱动-oracle.jdbc.driver.OracleDriver
      }
      catch (ClassNotFoundException e) 
      ...{
       e.printStackTrace();
      }
     } //禁止实例化
     private DBToolsX()...{}
     
     //获取连接方法
     public synchronized static Connection getConnection()
     ...{
      Connection con=null;
      try 
      ...{
       con=DriverManager.getConnection(URL,USER,PWD);
      } 
      catch (SQLException e)
      ...{
       e.printStackTrace();
      }
      return con;
     }
     
     //关闭ResultSet方法
     public static void closeResultSet(ResultSet rs)
     ...{
      try 
      ...{
       if(rs!=null)
        rs.close();
      } 
      catch (SQLException e) 
      ...{
       e.printStackTrace();
      }
     }
     
     //关闭Statement方法
     public static void closeStatement(Statement stmt)
     ...{
      try 
      ...{
       if(stmt!=null)
        stmt.close();
      } 
      catch (SQLException e) 
      ...{
       e.printStackTrace();
      }
     }
     
     //关闭本次连接方法
     public static void closeConnection(Connection con)
     ...{
      try 
      ...{
       if(con!=null)
        con.close();
      } 
      catch (SQLException e) 
      ...{
       e.printStackTrace();
      }
     }
     
     //数据库连接字符串
     private static String URL="";
     /**//*
       SQlServer2000的连接字符串:jdbc:microsoft:sqlserver://127.0.0.1:1433;DatabaseName=pubs
       MySQL5.x的连接字符串:jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=gb2312
       Oracle9i(thin)<无需WEB服务器端安装Oracle客户端>的连接字符串:jdbc:oracle:thin:@127.0.0.1:1521:TEMPDB
       Oracle9i(oci)的连接字符串:jdbc:oracle:oci8:@TEMPDB
     */
     //数据库用户名
     private static String USER="";
     //测试常用用户名:SQLServer2000-sa,MySQL5.x-root,Oracle9i-scott
     //数据库密码
     private static String PWD="";
     //测试常用密码:SQLServer2000-sa/空密码,MySQL5.x-root/a,Oracle9i-tiger
    }
    此类的具体使用方法可以参考我的BLOG文章
    http://blog.csdn.net/AXuan_Good_GAME/archive/2008/04/04/2250607.aspx
      

  10.   

    那个发错了,重发一下
    import java.sql.*;public class DBToolsX 
    {
    //静态块:加载数据库驱动
    static
    {
    try 
    {
    Class.forName("");
    //加载SQlServer2000驱动-com.microsoft.jdbc.sqlserver.SQLServerDriver
    //加载MySQL5.x驱动-com.mysql.jdbc.Driver
    //加载Oracle9i驱动-oracle.jdbc.driver.OracleDriver
    }
    catch (ClassNotFoundException e) 
    {
    e.printStackTrace();
    }
    } //禁止实例化
    private DBToolsX(){}

    //获取连接方法
    public synchronized static Connection getConnection()
    {
    Connection con=null;
    try 
    {
    con=DriverManager.getConnection(URL,USER,PWD);

    catch (SQLException e)
    {
    e.printStackTrace();
    }
    return con;
    }

    //关闭ResultSet方法
    public static void closeResultSet(ResultSet rs)
    {
    try 
    {
    if(rs!=null)
    rs.close();

    catch (SQLException e) 
    {
    e.printStackTrace();
    }
    }

    //关闭Statement方法
    public static void closeStatement(Statement stmt)
    {
    try 
    {
    if(stmt!=null)
    stmt.close();

    catch (SQLException e) 
    {
    e.printStackTrace();
    }
    }

    //关闭本次连接方法
    public static void closeConnection(Connection con)
    {
    try 
    {
    if(con!=null)
    con.close();

    catch (SQLException e) 
    {
    e.printStackTrace();
    }
    }

    //数据库连接字符串
    private static String URL="";
    /*
      SQlServer2000的连接字符串:jdbc:microsoft:sqlserver://127.0.0.1:1433;DatabaseName=pubs
      MySQL5.x的连接字符串:jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=gb2312
      Oracle9i(thin)<无需WEB服务器端安装Oracle客户端>的连接字符串:jdbc:oracle:thin:@127.0.0.1:1521:TEMPDB
      Oracle9i(oci)的连接字符串:jdbc:oracle:oci8:@TEMPDB
    */
    //数据库用户名
    private static String USER="";
    //测试常用用户名:SQLServer2000-sa,MySQL5.x-root,Oracle9i-scott
    //数据库密码
    private static String PWD="";
    //测试常用密码:SQLServer2000-sa/空密码,MySQL5.x-root/a,Oracle9i-tiger
    }
      

  11.   

    不断调用MSquery就会造成大量的数据库连接,每次的连接都没关。但是你是用ResultSet直接返回的,连接还不能关。
    不要偷懒,用HashMap把ResultSet的东西取出来存好,把rs和conn都关了吧
      

  12.   

    我不明白你为什么一定要返回一个ResultSet对象呢?如果你只是单一的想使用RS里面的数据的话 完全可以用ArrayList来储存 然后返回 在页面用ArrayList接收 利用循环输出数据就可以了 这样 执行完方法后 不就可以调用close方法关闭连接了吗?不知道这样能达到你的需求不!下面是个示例代码 仅供参考 嘿嘿 
    public class IndexManage {
        public ArrayList test(int id) {
            conn = da.getConnection();
            ArrayList al=new ArrayList();
            String sql = "查询语句";
            try {
                stmt = conn.prepareStatement(sql);
                stmt.setInt(1,id);
                stmt.setInt(2,0);
                rs = stmt.executeQuery();
                while (rs.next()) {
                    ProgramBean ab=new ProgramBean();   //储存数据的BEAN
                    ab.setDisplay_order(rs.getInt("display_order"));
                    ab.setP_name(rs.getString("p_name"));
                    ab.setId(rs.getInt("id"));
                    ab.setPic_url(rs.getString("pic_url"));
                    ab.setR_id(rs.getInt("r_id"));
                    ab.setP_type(rs.getInt("p_type"));
                    al.add(ab); //循环添加到ArrayList对象里
                }
            } catch (SQLException ex) {
                System.out.println(ex);
            } finally {
                da.close(conn, stmt, rs);//关闭与数据库的连接
            }
            return al;  //返回ArrayList集合 
        }
    }
    前台使用 :
    <%
    IndexManage im=new IndexManage();
    ArrayList al=new ArrayList();
    al=im.test(id);
    ProgramBean pb=new ProgramBean();for(int i0;i<al.size();i++)
      {
        pb=(ProgramBean)al.get(i);
        //这里做输出操作
       }
    %>
      

  13.   

    楼主的问题显然不是一行两行代码的问题,也不是某个方法的问题。在这里改任何一个方法都不解决问题。
    你必须分清一个概念connection只需要加载一次,多次运行,所以它应该是静态变量,如果需要多个connection就应该用线程去管理它。
    还有建议你方法和连接要分开不要都写在一个类里,当然用内部类也可以实现,但是很少有人这么用。
    我给你写个connectionManager把,这个类专门用于获取和关闭connection。你在其他的类的方法里要connection就去调用,用完了再关闭。
    在这里我用properties去配置你的用户名密码等。(最好这样配置)如果你是初学者,觉得不需要可以不引入properties文件。
    只需要把if (config == null) {config = new Properties();.......到return conn;那部分代码换成你自己的loadMSsqlDriver()里的那部分代码就可以了。
    然后你在你的方法类里只需要Connection conn = ConnectionManager.getConnection();就可以获取你的连接.然后用玩了就用connectionManager的close去关闭它.import java.io.InputStream;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    import java.util.Properties;import net.hr.dao.DataAccessException;public class ConnectionManager {
    private static ThreadLocal<Connection> localConn = new ThreadLocal<Connection>();
    private static Properties config; public static Connection getConnection() throws DataAccessException {
    Connection conn = localConn.get();
    if (conn == null) {
    conn = openConnection();
    localConn.set(conn);
    }
    return conn;
    } private static Connection openConnection() throws DataAccessException {
    try {
    if (config == null) {
    config = new Properties();
    InputStream in = ConnectionManager.class
    .getResourceAsStream("/jdbc.properties");
    config.load(in);
    }
    Class.forName(config.getProperty("jdbc.driver"));
    Connection conn = DriverManager.getConnection(config
    .getProperty("jdbc.url"), config.getProperty("jdbc.user"),
    config.getProperty("jdbc.password"));
    return conn;
    } catch (Exception e) {
    e.printStackTrace();
    throw new DataAccessException(e);
    }
    } @SuppressWarnings("unused")
    public static void closeConnection() {
    Connection conn = localConn.get();
    if (conn != null) {
    try {
    conn.close();
    } catch (SQLException e) {
    e.printStackTrace();
    throw new DataAccessException(e);
    }
    }
    localConn.set(null);
    } public static void setConfig(Properties config) {
    ConnectionManager.config = config;
    }
    }
      

  14.   


    差不多就是这个意思,你把loadMssqlDriver();的功能在其他的类里实现,connection一定是静态的。
    然后在使用出只需要调用连接就可以了。用玩了就关闭。
    我的那个connectionManager就是实现你的loadMSsqlDriver()功能的,如果你觉得用properties太麻烦可以把你的代码写到我的connectionManager中。
    但是一定要是静态变量,和用线程管理多个连接。然后有关闭就可以了。
      

  15.   

    感觉楼上那个bblog就写的很好了
    呵呵
    这个要看个人造诣的
    楼主别急着做眼前的
    你多写些代码
    很多代码 你一看就知道这样写不好了
    这个和自己有关系 
      

  16.   

    我建议对数据库的操作的代码不要放在jsp里,至少不要放在本页,需要值的话从另一个页面或servlet传到本页面,这样就不会每次刷新都向数据库请求一次
      

  17.   

    不想封装到List里的话,就用行集吧。这样你就可以安全地关掉连接了
    基本上与ResultSet操作方式完全一样。
      

  18.   

    1、事务控制方面会有问题
    2、一般不会直接返回ResultSet
      

  19.   

    采用単例模式,具体単例的应用我也不是很清楚,学习中
    public class DB {
        
         Connection conn=null;
            
        /** Creates a new instance of DB */
        private DB() {
        }
        
        private static DB instrance = null;
        
        public static DB getInstrance() {
         if ( instrance == null) {
         instrance = new DB();
         }
         return instrance;
        }
        /**
         *加载sqlserver驱动程序
         */
        public void loadMSsqlDriver()
        {
            try {
                Class.forName("驱动");
                conn = DriverManager.getConnection("链接");
            } catch (SQLException ex) {
                ex.printStackTrace();
            } catch (ClassNotFoundException ex) {
                ex.printStackTrace();
            }
        }
        /**
         *处理sqlServer数据库的查询操作,
         *传进去一查询语句,返回一个ResultSet结果集
         */
        public ResultSet MSquery(String querySql)
        {     
     
            ResultSet rs=null;
            try {
                Statement stmt=conn.createStatement();
                rs=stmt.executeQuery(querySql);
            } catch (SQLException ex) {
                ex.printStackTrace();
            } 
                
             return rs;
        }
        /**
         *处理sqlServer数据库 增 删 改 操作
         *会返回一个boolean值,true执行成功,false执行失败
         */
        public boolean MSupdate(String updateSql)
        {
      
            boolean check=false;
            int i=0;
            try {
                Statement stmt=conn.createStatement();
                i = stmt.executeUpdate(updateSql);
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
            if(i!=0)
                check=true;
            this.close();
            return check;
        }
        /**
         *关闭连接,将连接重新放回到池中
         */
        public void close()
        {
            try {
                if(conn!=null)
                this.conn.close();
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
        }
        
    }调用时采用DB.getInstrance().loadMSsqlserver();的方式,去掉DB中的方法的连接语句。
      

  20.   

    采用単例模式,具体単例的应用我也不是很清楚,学习中
    public class DB {
        
         Connection conn=null;
            
        /** Creates a new instance of DB */
        private DB() {
        }
        
        private static DB instrance = null;
        
        public static DB getInstrance() {
         if ( instrance == null) {
         instrance = new DB();
         }
         return instrance;
        }
        /**
         *加载sqlserver驱动程序
         */
        public void loadMSsqlDriver()
        {
            try {
                Class.forName("驱动");
                conn = DriverManager.getConnection("链接");
            } catch (SQLException ex) {
                ex.printStackTrace();
            } catch (ClassNotFoundException ex) {
                ex.printStackTrace();
            }
        }
        /**
         *处理sqlServer数据库的查询操作,
         *传进去一查询语句,返回一个ResultSet结果集
         */
        public ResultSet MSquery(String querySql)
        {     
     
            ResultSet rs=null;
            try {
                Statement stmt=conn.createStatement();
                rs=stmt.executeQuery(querySql);
            } catch (SQLException ex) {
                ex.printStackTrace();
            } 
                
             return rs;
        }
        /**
         *处理sqlServer数据库 增 删 改 操作
         *会返回一个boolean值,true执行成功,false执行失败
         */
        public boolean MSupdate(String updateSql)
        {
      
            boolean check=false;
            int i=0;
            try {
                Statement stmt=conn.createStatement();
                i = stmt.executeUpdate(updateSql);
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
            if(i!=0)
                check=true;
            this.close();
            return check;
        }
        /**
         *关闭连接,将连接重新放回到池中
         */
        public void close()
        {
            try {
                if(conn!=null)
                this.conn.close();
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
        }
        
    }调用时采用DB.getInstrance().loadMSsqlserver();的方式,去掉DB中的方法的连接语句。
      

  21.   

    原来在IBM网站上看到一篇很不错的介绍各种缓存行集的文章,找不到了,只找到这个,
    凑合看吧:
    http://dev.csdn.net/Develop/article/28/65251.shtm
      

  22.   

    不要返回ResultSet就可以了!
    你可以把结果集组装成一个集合对象返回去
      

  23.   

    如果只是要求一次链接的话建议使用单态模式来获取Connection
    如果有多个链接的话你想要控制链接的个数的话就自己写个连接池,呵呵
      

  24.   

    单态模式代码应该就是这样的。加到你的代码里就成了。
    你在查询或其他操作的时候打开数据库链接用getConnection()方法就行了,
    创建了一次链后你只要不关闭下次你调用getConnection()方法的时候还是用的原来的链接 
            private static Connection conn = null;
    private static Connection getConnection(){
    if(conn == null){
    try {
                Class.forName("org.logicalcobwebs.proxool.ProxoolDriver");
                conn = DriverManager.getConnection("proxool.myoracle");
            } catch (SQLException ex) {
                ex.printStackTrace();
            } catch (ClassNotFoundException ex) {
                ex.printStackTrace();
            }
    }
    return conn;
    }
      

  25.   

    不好意思,写错了一句
    private static Connection conn = null; 
    改成
    private static Connection conn ;
    不要那个 = null,呵呵
      

  26.   


    private Connection conn=null;
    private PreparedStatement ps=null;private Connection loadMSsqlDriver()
        {
            try {
                Class.forName("org.logicalcobwebs.proxool.ProxoolDriver");
                return DriverManager.getConnection("proxool.myoracle");
            } catch (SQLException ex) {
                ex.printStackTrace();
                return null;
            } catch (ClassNotFoundException ex) {
                ex.printStackTrace();
                return null;
            }
        }
    public ArrayList MSquery(String querySql)
        {     
            conn = this.loadMSsqlDriver()     
            ResultSet rs=null;
            ArrayList al = new ArrayList();
            try {
                ps=conn.prepareStatement(querySql);
                rs=ps.executeQuery();
                while (rs.next()) {
                //将rs内容保存到ArrayList中
                  }
                return al;
            } catch (SQLException ex) {
                ex.printStackTrace();
                return null;
            }finally{
                 this.close();
            }
        }
    public void close()
        {
            try {
                if(ps!=null)
                ps.close();
                if(conn!=null)
                conn.close();
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
        }这样写吧
      

  27.   

    哦,你已经用proxool了阿,那你用完为什么不关呢。
      

  28.   


    楼主:到目前为止没看到你的JSP,不知道你怎么调用的DB类,何时调用close()。你在浪费大家的时间
      

  29.   

    jsp页面调用数据库代码<%
       ResultSet rs = qiu.MSquery(
       "select * from table where ... order by id asc");
    %>
      

  30.   

    这年头为什么不用spring呢?早不用担心这些问题了。