简体   繁体   English

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

[英]How to share a databse connection among classes? (JDBC)

I'm trying to figure out how to share an established connection to a database among classes to execute different SQL statements. 我试图弄清楚如何在类之间共享与数据库的已建立连接以执行不同的SQL语句。 I read through some of the topics, but as I'm fairly new to programming I have a hard time to adapt the given information to my problem. 我通读了一些主题,但是由于我是编程的新手,因此很难适应给定的信息以解决我的问题。

Problem: I have two classes with one opening a connection to a database, executing some SQL statments and calling the other class to do the same only using different tables and SQL statments. 问题:我有两个类,一个类打开与数据库的连接,执行一些SQL语句,然后调用另一个类仅使用不同的表和SQL语句执行相同的操作。 Now as long as I run the classes separatly with their own main method and connections everything works fine. 现在,只要我使用自己的主方法和连接分别运行这些类,一切就可以正常工作。 But as one class calls the other I get different Exceptions, depending on my workarounds I tried so far (either MySQLNonTransientConnectionException: Data source rejected establishment of connection or a StackOverflowException ). 但是当一个类调用另一个类时,我会得到不同的异常,这取决于到目前为止我尝试过的解决方法( MySQLNonTransientConnectionException:数据源拒绝建立连接StackOverflowException )。

Here is how I'm trying to established a connection that is used to execute some sql operations in two different classes: 这是我尝试建立的连接,该连接用于执行两个不同类中的某些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();}
    }
}

Why can't class B use the connection of ClassA, for instance by doing something like this (This leads to a StackOverflow): 为什么类B无法使用类A的连接,例如通过执行以下操作(这会导致StackOverflow):

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

On the other hand, if I'm trying to establish two separate Connections (using the same code as above) to the same database (running at the same time) I get the MySQLNonTransientConnectionException: Data source rejected establishment of connection. 另一方面,如果我试图建立到同一数据库(同时运行)的两个单独的Connections(使用与上面相同的代码)(同时运行),则会得到MySQLNonTransientConnectionException:数据源拒绝建立连接。

What's the best way to handle this? 处理此问题的最佳方法是什么? I stumbled upon ConnectionPooling in the forums, but I couldn't find a beginner friendly source to elaborate how to put this into practice. 我在论坛上偶然发现了ConnectionPooling,但找不到适合初学者的资料来详细说明如何将其付诸实践。 Is there a straight forward way to ensure different classes can connect and operate on one database? 是否有一种直接的方法来确保不同的类可以连接并在一个数据库上运行?

Thanks for any feedback 感谢您的任何反馈

I would avoid putting the connection in a static variable. 我会避免将连接放在静态变量中。 It doesn't make a whole lot of difference in your particular instance but it would be best to not get into the habit of doing it that way. 在您的特定实例中,这并没有太大的区别,但是最好不要养成那样的习惯。

You should create one controlling class the creates the database connection, then passes it to the other two classes as method parameters. 您应该创建一个控制类,然后创建数据库连接,然后将其作为方法参数传递给其他两个类。 This way the controlling class can handle any exception thrown by the other classes and make sure the connection is closed properly. 这样,控制类可以处理其他类抛出的任何异常,并确保正确关闭了连接。

You can achieve that by creating a non-static global variable for Connection in Class A and then creating a non-static public method to return this connection, as shown below. 您可以通过为Class A中的Connection创建一个非静态全局变量,然后创建一个非静态public方法来返回此连接来实现,如下所示。

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;
    }
}

And then in your class B, you can do something like this. 然后在B类中,您可以执行以下操作。

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

Hope this helps you out. 希望这可以帮助你。

You should create one controlling class the creates the database connection, then passes it to the other two classes as method parameters. 您应该创建一个控制类,然后创建数据库连接,然后将其作为方法参数传递给其他两个类。

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;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM