2012-06-18 57 views
1

我有有很多方法操縱數據庫中的DAO類。我使用一個連接對象爲所有類似的方法(Database.connect()返回一個連接對象):如何在java中爲許多方法創建一個數據庫連接?

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

這是實例爲每個方法一個新的連接並關閉它一個很好的做法?我現在有錯誤說「連接關閉後不允許任何操作」雖然我在每個方法的開始初始化連接並在最後關閉連接。或者最好使用相同的連接對象,並有一個單獨的方法,當我打電話時關閉它?

+3

如果這些方法相互調用,內部通話將過早關閉連接,從而使你的錯誤看到。 –

+0

你必須提供有關例外的更多細節!例如StackTrace或Line Number會很有幫助! – adranale

+0

[JDBC最佳實踐]可能的重複(http://stackoverflow.com/questions/6169301/jdbc-best-practice) –

回答

0

創建兩個功能,一個是

connection() 

另一個用於

disconnection() 

呼叫每個方法

function method() 
{ 
    //call 

    connection(); 

    //code; 

    //call 

    disconnection(); 
    } 
0

這些方法是什麼使一個全球性的連接,當你打開連接點在每種方法中。 當您從method1調用method2時,可能會發生這種情況,它會關閉方法1使用的連接

通常,最佳做法是在應用程序生命週期中創建連接一次,並關閉應用程序關閉/退出時的連接,因爲打開和關閉連接。

+0

那麼如何確定何時關閉連接?或者,你能舉出一個如此安全退出的例子嗎? – iozee

0

您的代碼不是線程安全的,因爲jdbc連接不能同時使用! 請更改連接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

: 公共無效方法1(){ 嘗試 { 連接CON = ConnectionHelper.getConnection(); } 最後 { ConnectionHelper.closeConnection(); } }

+0

這是否提供同步? – alaster

+1

你不需要同步一個ThreadLocal,它是一個Thread作用域中的變量。 –

2

ExampleDAOImpl的對象不是線程安全的。因此,如果多個線程使用相同的ExampleDAOImpl對象和調用方法的同時,也可能發生一個關閉那麼其他線程試圖使用它的連接。

可能的解決方案:

  • 確保ExampleDAOImpl對象不用在多線程環境中使用。這仍然很容易出錯。
  • 更好的建議:而不是使用一個單一的Connection對象,使用ConnectionPool你從它完成後能得到在每個方法的開始和自由的連接。
0

如果您使用的是連接池的實現像BoneCP,這是完全沒有打開新的連接爲每個方法,只是確保該方法不引用實例變量,而是一個局部變量。

另一方面,如果您沒有可用的連接池並僅使用一個連接,則必須找到合適的位置來關閉該連接,因爲在沒有池的情況下獲取新連接池非常昂貴。

0

如果你想要的是幹你的代碼, 然後使用抽象類和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); 
    } 

} 
相關問題