2011-09-02 41 views
12

thể trùng lặp:
when to close Connection, Statement, PreparedStatement and ResultSet in JDBCThực hành tốt: Kết nối JDBC

Tôi đã viết một wrapper đơn giản cho một kết nối JDBC và nó hoạt động nhưng tôi muốn cải thiện nó với các thông lệ tốt nhất càng tốt. Về cơ bản nó có các phương pháp như open(), close(), isOpened(), select(), insert(), update(), delete()batch(). Để đơn giản, tôi sẽ chỉ đăng ở đây 4 phương pháp đầu tiên.

public class Query{ 
    private Connection con; 
    private PreparedStatement ps; 
    private ResultSet rs; 

    //Database.open() returns a Connection ready to use 
    public void open (Database database) throws DatabaseException, SQLException{ 
     if (!isOpened()){ 
      con = database.open(); 
     } 
    } 

    public void close() throws SQLException{ 
     if (isOpened()){ 
      if (ps != null) ps.close(); 
      con.close(); 
      con = null; 
     } 
    } 

    public boolean isOpened(){ 
     return con != null; 
    } 

    //The query string is the query without the word "select" and can use placeholders (?) 
    //The args param it's just an array owith the values of this placeholders 
    public ResultSet select (String query, Object[] args) throws SQLException{ 
     if (ps != null) ps.close(); 

     if (isOpened()){ 
      ps = con.prepareStatement ("select " + query); 
      if (args != null){ 
       for (int i=0; i<args.length; i++){ 
        ps.setObject (i+1, args[i]); 
       } 
      } 
      rs = ps.executeQuery(); 
     } 

     return rs; 
    } 
} 

Ghi chú:

  • Các đối tượng truy vấn tương tự có thể được tái sử dụng, ví dụ như mở và đóng cửa nó, và sau khi mở một lần nữa.
  • Tôi không đóng kết nối cho mỗi truy vấn, tôi chỉ đóng tuyên bố chuẩn bị (điều này là đúng hay tôi có thể rời khỏi chuẩn bị tuyên bố mở được vì đối tượng Connection sẽ đóng nó?)
  • Khi tôi đóng số Connection, tất cả các số PreparedStatement s và của chúng ResultSet cũng bị đóng, phải không?

Cách sử dụng:

Database database; 

//Database initialization 

Query query = new Query(); 


query.open (database); 

ResultSet rs = query.select ("* from user where name=?", new String[]{ "MyName" }); 
doSomethingWithResult1 (rs); 

//Connection is not closed here 

ResultSet rs = query.select ("coordx from point where coordy=? and coordz=?", new Float[]{ 0.1, 0.2 }); 
doSomethingWithResult2 (rs); 

query.close(); 


query.open (database); 

ResultSet rs = query.select ("* from user where name=?", new String[]{ "MyName" }); 
doSomethingWithResult1 (rs); 

//Connection is not closed here 

ResultSet rs = query.select ("coordx from point where coordy=? and coordz=?", new Float[]{ 0.1, 0.2 }); 
doSomethingWithResult2 (rs); 

query.close(); 

Bạn nghĩ gì? Tôi có nên đóng và mở kết nối sau mỗi truy vấn không? Tôi có thể để mở PreparedStatement sau mỗi truy vấn trên cùng một kết nối không? Đó là một thiết kế tốt?

+7

Kết nối đóng và mở lại cho mỗi truy vấn là một ý tưởng tồi. Thực hiện một kết nối thực sự, thực sự tốn kém. – bdares

+1

Sau đó, tôi có thể để mở PreparedStatement hay tôi nên đóng nó cho mọi truy vấn? –

+0

Bạn có thể để mọi thứ mở cho đến khi bạn thực sự được thực hiện bằng cách sử dụng DB. Đóng một kết nối sẽ theo dõi và đóng tất cả các công cụ (câu lệnh, resultsets) mà nó sinh ra. – bdares

Trả lời

12

Bạn phải đóng PreparedStatement sau khi đã hoàn tất và trước khi tạo một kết nối mới trên cùng một kết nối. Tôi đã có những vấn đề nghiêm trọng vì tôi không đóng PreparedStatements. Nó bật ra rằng trên máy chủ cơ sở dữ liệu có nguồn tài nguyên được phân bổ chỉ được giải phóng sau khi một cuộc gọi rõ ràng của PreparedStatement.close().

Như bdares đã nhận xét, kết nối sẽ được mở và đóng càng ít càng tốt.

1

paectise tốt nhất là: sử dụng đối tượng kết nối duy nhất cho tất cả các truy vấn nếu các hàng đợi đó là một phần của cùng một phương thức và cho mỗi truy vấn đóng PreparedStatement, sau khi được sử dụng.

1

Sử dụng hồ bơi Kết nối. Vì vậy, bạn không tiếp tục tạo.

+0

Nhóm kết nối được tạo khi tôi khởi tạo cơ sở dữ liệu. Kết nối mà phương thức database.open() của tôi trả về là một kết nối từ một pool vì tôi đang sử dụng nguồn dữ liệu. –

5

kết nối tổng hợp

Sử dụng một hồ bơi kết nối. Mỗi giao dịch trong ứng dụng của bạn sẽ nhận được kết nối từ nhóm này, thực hiện tất cả những thứ cần thiết, khôi phục hoặc cam kết và đóng kết nối (nó sẽ trả về kết nối với nhóm).

Bạn có thể cung cấp cho bạn Đối tượng truy vấn một tham chiếu đến hồ bơi và mở sẽ nhận được kết nối và đóng sẽ đóng nó (trả lại thực tế).

tuyên bố chuẩn bị

Cố gắng tái sử dụng tuyên bố chuẩn bị của bạn cho các truy vấn tương tự. Bằng cách đó, DB sẽ sử dụng lại kế hoạch truy vấn trước đó và nó sẽ nhanh hơn. Nó có rất nhiều ý nghĩa nếu bạn đang thực hiện rất nhiều truy vấn của cùng một hình thức.

Làm cách nào?

  • Duy trì PS cuối cùng mở
  • Nếu bạn đóng kết nối hoặc bất cứ điều gì, hãy đóng nó
  • nếu bạn truy vấn cho chuỗi truy vấn cùng hơn việc tái sử dụng trước đây PS bạn đã lưu
  • nếu nó không giống nhau chuỗi truy vấn ... đóng và tạo một chuỗi mới
Các vấn đề liên quan