如何在类之间共享数据库连接? (JDBC)

时间:2014-10-30 11:57:01

标签: java mysql jdbc

我正在试图弄清楚如何在类之间共享与数据库建立的连接以执行不同的SQL语句。 我阅读了一些主题,但由于我对编程很新,所以我很难将给定的信息适应我的问题。

问题:我有两个类,一个打开与数据库的连接,执行一些SQL语句并调用另一个类只使用不同的表和SQL语句来执行相同的操作。 现在,只要我使用自己的main方法和连接分别运行类,一切正常。但是当一个类调用另一个类时,我会得到不同的异常,这取决于我到目前为止尝试的变通方法( MySQLNonTransientConnectionException:数据源拒绝建立连接 StackOverflowException )。 / p>

以下是我试图建立一个用于在两个不同的类中执行某些sql操作的连接:

public ClassA{

    public static Connection dbConn;

    //Set up a connection to the database
    String dbURL = "jdbc:mysql://<some database>"; //put host, port and database here
    Properties connectionProbs = new Properties();
    connectionProbs.put("user", "root"); //insert USER here
    connectionProbs.put("password", "root"); //insert PASSWORD here

    dbConn = null;
    try{
        dbConn = DriverManager.getConnection(dbURL, connectionProbs);

        PreparedStatement useStmt;
        try{
            useStmt = dbConn.prepareStatement("USE <some database>"); //insert DATABASE here
            useStmt.executeUpdate();
        }
        catch(SQLException e){
            e.printStackTrace();
        }
        //Do some SQL operations
        //Call class B to do some SQL operations using the same connection

    }
    catch(SQLException e){
        System.err.println("There was a problem connecting to the database");
        e.printStackTrace();
    }
    finally{
        if(dbConn != null)
            try{dbConn.close();}catch(SQLException e){e.printStackTrace();}
    }
}

为什么B类不能使用ClassA的连接,例如通过这样做(这会导致StackOverflow):

PreparedStatement Stmt = ClassA.dbConn.prepareStatement("INSERT INTO table(ID, name) VALUES (?,?)");

另一方面,如果我试图建立两个单独的连接(使用与上面相同的代码)到同一个数据库(同时运行),我得到MySQLNonTransientConnectionException:数据源拒绝建立连接。 / p>

处理此问题的最佳方法是什么?我在论坛中偶然发现了ConnectionPooling,但我找不到一个初学友好的来源来详细说明如何将其付诸实践。有没有直接的方法来确保不同的类可以在一个数据库上连接和操作?

感谢您的反馈

3 个答案:

答案 0 :(得分:0)

我会避免将连接放在静态变量中。它在你的特定实例中没有产生很大的不同,但最好不要养成这样做的习惯。

您应该创建一个控制类来创建数据库连接,然后将其作为方法参数传递给其他两个类。这样,控制类可以处理其他类抛出的任何异常,并确保正确关闭连接。

答案 1 :(得分:0)

您可以通过为A类中的Connection创建非静态全局变量,然后创建一个非静态公共方法来返回此连接来实现此目的,如下所示。

public ClassA{
    // non-static global private Connection object
    private Connection dbConn = null;

    // non-static public method to get dbConn connection object
    public Connection getConnection() {
        // this condition will check if the Connection is not already open then open it.
        if(null == dbConn) {
            //Set up a connection to the database
            String dbURL = "jdbc:mysql://<some database>"; //put host, port and database here
            Properties connectionProbs = new Properties();
            connectionProbs.put("user", "root"); //insert USER here
            connectionProbs.put("password", "root"); //insert PASSWORD here

            try{
                dbConn = DriverManager.getConnection(dbURL, connectionProbs);

                PreparedStatement useStmt;
                try{
                    useStmt = dbConn.prepareStatement("USE <some database>"); //insert DATABASE here
                    useStmt.executeUpdate();
                }
                catch(SQLException e){
                    e.printStackTrace();
                }
                //Do some SQL operations
                //Call class B to do some SQL operations using the same connection

            }
            catch(SQLException e){
                System.err.println("There was a problem connecting to the database");
                e.printStackTrace();
            }
            finally{
                if(dbConn != null)
                    try{dbConn.close();}catch(SQLException e){e.printStackTrace();}
            }
        }
        return dbConn;
    }
}

然后在你的B班,你可以做这样的事情。

A a = new A();
PreparedStatement Stmt = a.getConnection().prepareStatement("INSERT INTO table(ID, name) VALUES (?,?)");

希望这可以帮助你。

答案 2 :(得分:0)

  

您应该创建一个控制类来创建数据库连接,然后将其作为方法参数传递给其他两个类。

public class ConnectionManager {

    private static String url = "jdbc:mysql://localhost:3306/DbName";
    private static String username = "YourUsername";
    private static String password = "yourDbPass";
    private static Connection con;

    public static Connection getConnection() throws Exception {
      con = DriverManager.getConnection(url, username, password);
        return con;
    }


}
public class main {

    public static void main(String[] args) throws Exception {
        Connection con = null;
        con = ConnectionManager.getConnection();


        CrudCity s = new CrudCity();
        s = s.read(con);
        System.out.println(s);

        CrudCountry c = new CrudCountry();
        c = c.read(con);
        System.out.println(c);

        CrudCountryLanguage lang = new CrudCountryLanguage();
        lang = lang.read(con);
        System.out.println(lang);


    }

}
  public class CrudCity extends City implements CrudInterface {


    public CrudCity read(Connection con) throws Exception{
        CrudCity p = new CrudCity();

        Statement stmt = con.createStatement();
        ResultSet rs = stmt.executeQuery("SELECT ID,Name,CountryCode FROM world.city");
        while (rs.next()) {
            p.setId(rs.getInt("ID"));
            p.setName(rs.getString("Name"));
            p.setCountryCode(rs.getString("CountryCode"));

        }
        rs.close();
        return p;
    }
}
public class CrudCountry extends Country implements CrudInterface{

    public CrudCountry read(Connection con) throws Exception{
        CrudCountry c = new CrudCountry();
        Statement stmt =con.createStatement();
        ResultSet rs = stmt.executeQuery("SELECT Code,Name,Continent FROM world.country");
        while (rs.next()) {
            c.setCountryCode(rs.getString("Code"));
            c.setCountryName(rs.getString("Name"));
            c.setCodeContinent(rs.getString("Continent"));
        }

        rs.close();

        return c;
    }
}