如何在java中为多个方法建立一个数据库连接?

如何在java中为多个方法建立一个数据库连接?,java,database,mysql-connector,Java,Database,Mysql Connector,我有一个DAO类,它有许多方法操作数据库。我对所有类似的方法使用一个连接对象(Database.connect()返回一个连接对象): 为每个方法实例化一个新连接并关闭它,这是一个好的做法吗?虽然我在每个方法的开头初始化连接,并在最后关闭连接,但是我现在有错误说“连接关闭后不允许操作”。或者最好使用同一个连接对象,并有一个单独的方法在我调用它时关闭它?为一个对象创建两个函数 connection() 另一个 disconnection() 在每个方法中调用这些方法 functio

我有一个DAO类,它有许多方法操作数据库。我对所有类似的方法使用一个连接对象(Database.connect()返回一个连接对象):


为每个方法实例化一个新连接并关闭它,这是一个好的做法吗?虽然我在每个方法的开头初始化连接,并在最后关闭连接,但是我现在有错误说“连接关闭后不允许操作”。或者最好使用同一个连接对象,并有一个单独的方法在我调用它时关闭它?

为一个对象创建两个函数

  connection()
另一个

  disconnection()
在每个方法中调用这些方法

  function method()
 {
  //call 

  connection();

  //code;

  //call 

     disconnection();
  } 

在每个方法中打开连接时建立全局连接的意义是什么。 当您从method1调用method2时,可能会发生这种情况,因为它会关闭method1使用的连接


一般来说,良好的做法是在应用程序生命周期中创建一次连接,并在应用程序关闭/退出时关闭连接,因为打开和关闭连接会产生成本。

您的代码不是线程安全的,因为jdbc连接不能同时使用! 请将Connection con更改为ThreadLocal,并添加两种连接和断开方法

代码如下所示:

public class ConnectionHelper
{
private static ThreadLocal<Connection> con = new ThreadLocal<Connection>();

protected Connection getConnection()
{
if(con.get() ==null)
{
con.set(Database.connect());
}
return con.get();
}

protected Connection closeConnection()
{
if(con.get() !=null)
{
con.get().close;
}
}
}
公共类ConnectionHelper
{
private static ThreadLocal con=new ThreadLocal();
受保护的连接getConnection()
{
if(con.get()==null)
{
con.set(Database.connect());
}
return con.get();
}
受保护的连接closeConnection()
{
if(con.get()!=null)
{
con.get().close;
}
}
}
在你的道中: 公共无效方法1(){ 尝试 { Connection con=ConnectionHelper.getConnection(); } 最后 { ConnectionHelper.closeConnection(); }
}类
ExampleDAOImpl
的对象不是线程安全的。因此,如果多个线程同时使用相同的
ExampleDAOImpl
对象和调用方法,则可能会出现一个线程关闭连接,而另一个线程尝试使用该连接的情况

可能的解决办法:

  • 确保在多线程上下文中从不使用
    ExampleDAOImpl
    对象。这仍然容易出错
  • 更好的建议:不要使用单个
    连接
    对象,而是使用
    连接池
    在每个方法的开头获取连接,并在完成后释放它

如果您使用的是连接池实现,例如,为每个方法打开新连接完全可以,只要确保该方法不引用实例变量,而是引用局部变量即可


另一方面,如果您没有可用的连接池并且只使用一个连接,则必须找到一个合适的位置来关闭该连接,因为获得没有连接池的新连接非常昂贵。

如果您想干燥代码, 然后使用抽象类和lambda

class ExampleDAOImpl implements ExampleDAO{

    // With lambdas
    public void method1 () {
       withConnection( (Connection con) -> {
           // do whatever you want with the connection
           // no need to open or close it
       })
    }

    // Old style abstract class
    public void method2 () {
       withConnection(new TaskExecutor(){
          void doStuff(Connection con){
             // do whatever you want with the connection
             // no need to open or close it
          }
       })
    }

    // This is the magic you have to add.
    private void withConnection(TaskExecutor executer){
        // Instantiate it to avoid race conditions
        // good thing this is the only place
        // you have to worry about opening and closing it
        Connection con = Database.connect();
        executer.doStuff(con);
        con.close();
    }

    private abstract class TaskExecutor{
        abstract void doStuff(Connection con);
    }

}

通过为所有方法创建一个连接,我解决了自己的问题:

 public void generateTestData() throws SQLException, ClassNotFoundException, IOException {
    ConnectionToDatabase connectionToDatabase = new ConnectionToDatabase();
    try (Connection connection = connectionToDatabase.connectToDatabase()) {
        {
            generateGroups(connection);
            generateCourses(connection);
            assignCoursesToStudents(connection);
        }
    }
}

对于smb来说,这可能很有用:)

如果这些方法相互调用,内部调用将过早地关闭连接,从而导致您看到的错误。您必须提供有关异常的更多详细信息!例如StackTrace或行号会很有帮助!可能是重复的,或者最好使用相同的连接对象-尝试一下。如果您在程序的整个生命周期中使用数据库,请在程序启动时打开连接,并在退出时关闭。那么您如何确定何时关闭连接?或者,你能举一个这样一个安全出口的例子吗?这提供了同步吗?你不需要对ThreadLocal进行同步,它是线程作用域中的一个变量。
 public void generateTestData() throws SQLException, ClassNotFoundException, IOException {
    ConnectionToDatabase connectionToDatabase = new ConnectionToDatabase();
    try (Connection connection = connectionToDatabase.connectToDatabase()) {
        {
            generateGroups(connection);
            generateCourses(connection);
            assignCoursesToStudents(connection);
        }
    }
}