[英]how to make a one database connection for many methods in java?
我有一個 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();
}
}
這是為每個方法實例化一個新連接並關閉它的好習慣嗎? 我現在有錯誤說“連接關閉后不允許操作”雖然我在每個方法的開頭初始化連接並在最后關閉它。 或者最好使用相同的連接對象並有一個單獨的方法在我調用它時關閉它?
ExampleDAOImpl
類的對象不是線程安全的。 因此,如果多個線程同時使用相同的ExampleDAOImpl
對象並調用方法,則可能會發生一個關閉連接然后另一個線程嘗試使用它的情況。
可能的解決方案:
ExampleDAOImpl
對象永遠不會在多線程上下文中使用。 這仍然容易出錯。Connection
對象,使用ConnectionPool
來獲得在每個方法的開始的連接,並釋放它你從它完成之后。創建兩個函數一個用於
connection()
另一個為
disconnection()
在每個方法中調用這些方法
function method()
{
//call
connection();
//code;
//call
disconnection();
}
在每種方法中打開連接時建立全局連接有什么意義。 當您從方法 1 調用方法 2 時,這可能會發生,它會關閉方法 1 使用的連接
通常,好的做法是在應用程序生命周期中創建一次連接並在應用程序關閉/退出時關閉連接,因為打開和關閉連接會產生成本。
你的代碼不是線程安全的,因為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(); } }
如果您正在使用像BoneCP這樣的連接池實現,那么為每個方法打開新連接是完全沒問題的,只需確保該方法不引用實例變量,而是一個局部變量。
另一方面,如果您沒有可用的連接池並且只使用一個連接,則必須找到一個合適的位置來關閉該連接,因為在沒有連接池的情況下獲取新連接非常昂貴。
如果你想要干你的代碼,那么使用抽象類和 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);
}
}
我通過為所有方法創建一個連接解決了我自己的問題:
public void generateTestData() throws SQLException, ClassNotFoundException, IOException {
ConnectionToDatabase connectionToDatabase = new ConnectionToDatabase();
try (Connection connection = connectionToDatabase.connectToDatabase()) {
{
generateGroups(connection);
generateCourses(connection);
assignCoursesToStudents(connection);
}
}
}
也許對 smb 會有用 :)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.