1

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

class ExampleDAOImpl implements ExampleDAO{
  private Connection con = null;

  public void method1 () {
   con = Database.connect();
   ....
   con.close();
  }

  public void method2 () {
   con = Database.connect();
   ....
   con.close();
  }

 public void method1 () {
   con = Database.connect();
   ....
   con.close();
  }
}

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

4

7 回答 7

2

ExampleDAOImpl的对象不是线程安全的。因此,如果多个线程同时使用同一个ExampleDAOImpl对象并调用方法,则可能会发生一个关闭连接然后另一个线程尝试使用它的情况。

可能的解决方案:

  • 确保ExampleDAOImpl永远不会在多线程上下文中使用对象。这仍然容易出错。
  • 更好的建议:不要使用单个Connection对象,而是使用 aConnectionPool在每个方法的开头获取连接,并在完成后释放它。
于 2012-06-18T11:56:59.960 回答
0

创建两个功能之一

  connection()

另一个为

  disconnection()

在每个方法中调用这些方法

  function method()
 {
  //call 

  connection();

  //code;

  //call 

     disconnection();
  } 
于 2012-06-18T11:44:38.407 回答
0

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

通常,良好的做法是在应用程序生命周期中创建一次连接并在应用程序关闭/退出时关闭连接,因为打开和关闭连接是有成本的.

于 2012-06-18T11:45:50.340 回答
0

您的代码不是线程安全的,因为 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;
}
}
}

在您的 DAO 中: public void method1 () { try { Connection con = ConnectionHelper.getConnection(); } 最后 { ConnectionHelper.closeConnection(); } }

于 2012-06-18T11:55:02.083 回答
0

If you are using a Connection Pool implementation like BoneCP, it is perfectly fine to open new connections for each method, just ensure that the method does not reference the instance variable, but rather a local variable.

On the other hand if you have no connection pool available and working with only one connection, you will have to find a suitable place to close that connection, since getting new ones without a pool is quite expensive.

于 2012-06-18T12:00:45.953 回答
0

如果你想要干你的代码,那么使用抽象类和 lambdas

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

}
于 2016-12-16T08:08:36.527 回答
0

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

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

也许对于 smb 会很有用:)

于 2020-02-27T11:19:40.213 回答