我有一个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();
}
}
这是一个很好的做法,为每个方法实例化一个新连接并关闭它吗?我现在有错误说“连接关闭后不允许任何操作”虽然我在每个方法的开头初始化连接并在结束时关闭它。或者最好使用相同的连接对象,并有一个单独的方法,当我调用它时关闭它?
答案 0 :(得分:2)
类ExampleDAOImpl
的对象不是线程安全的。因此,如果多个线程使用相同的ExampleDAOImpl
对象并同时调用方法,则可能会发生关闭连接然后另一个线程尝试使用它的情况。
可能的解决方案:
ExampleDAOImpl
对象永远不会在多线程上下文中使用。这仍然容易出错。Connection
对象,而是使用ConnectionPool
在每个方法的开头获取连接,并在完成后释放它。答案 1 :(得分:0)
为
创建两个函数1 connection()
另一个
disconnection()
在每个方法中调用这些方法
function method()
{
//call
connection();
//code;
//call
disconnection();
}
答案 2 :(得分:0)
在每种方法中打开连接时,建立全局连接的重点是什么。 当你从method1调用method2它关闭方法1使用的连接时,很可能发生这种情况 通常,良好的做法是在应用程序生命周期中创建一次连接并关闭应用程序关闭/退出时的连接,因为打开和关闭连接的成本。
答案 3 :(得分: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(){ 尝试 { Connection con = ConnectionHelper.getConnection(); } 最后 { ConnectionHelper.closeConnection(); } }
答案 4 :(得分:0)
如果您正在使用像BoneCP这样的连接池实现,那么为每个方法打开新连接是完全正常的,只需确保该方法不引用实例变量,而是引用局部变量。
另一方面,如果您没有可用的连接池并且只使用一个连接,则必须找到一个合适的位置来关闭该连接,因为在没有池的情况下获取新连接非常昂贵。
答案 5 :(得分: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);
}
}
答案 6 :(得分:0)
我通过为所有方法创建一个连接解决了自己的问题:
public void generateTestData() throws SQLException, ClassNotFoundException, IOException {
ConnectionToDatabase connectionToDatabase = new ConnectionToDatabase();
try (Connection connection = connectionToDatabase.connectToDatabase()) {
{
generateGroups(connection);
generateCourses(connection);
assignCoursesToStudents(connection);
}
}
}
也许对smb有用:)