Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Đôi khi NullPointerException trong ResultSetImpl.checkColumnBounds hoặc ResultSetImpl.getStringInternal

Đã lâu rồi tôi không đăng câu hỏi này và tôi muốn đăng câu trả lời mô tả chính xác trường hợp dẫn đến NullPointerException phức tạp này .

Tôi nghĩ rằng điều này có thể giúp những độc giả trong tương lai gặp phải trường hợp ngoại lệ khó hiểu như vậy suy nghĩ kỹ hơn, vì tôi có hầu hết mọi lý do để nghi ngờ đây là lỗi trình kết nối mysql, mặc dù rốt cuộc thì không phải vậy.

Trong khi điều tra ngoại lệ này, tôi chắc chắn rằng ứng dụng của mình không thể đóng kết nối DB trong khi cố đọc dữ liệu từ nó, vì các kết nối DB của tôi không được chia sẻ trên các chuỗi và nếu cùng một chuỗi đã đóng kết nối và sau đó cố gắng truy cập nó, một ngoại lệ khác nên đã được ném ra (một số SQLException ). Đó là lý do chính khiến tôi nghi ngờ có lỗi trình kết nối mysql.

Hóa ra là có hai luồng truy cập vào cùng một kết nối sau tất cả. Khó tìm ra lý do khiến điều này xảy ra là một trong những chuỗi này là một chuỗi thu gom rác .

Quay lại mã tôi đã đăng:

Connection conn = ... // the connection is open
...
for (String someID : someIDs) {
    SomeClass sc = null;
    PreparedStatement
        stmt = conn.prepareStatement ("SELECT A, B, C, D, E, F, G, H FROM T WHERE A = ?");
    stmt.setString (1, "someID");
    ResultSet res = stmt.executeQuery ();
    if (res.next ()) {
        sc = new SomeClass ();
        sc.setA (res.getString (1));
        sc.setB (res.getString (2));
        sc.setC (res.getString (3));
        sc.setD (res.getString (4));
        sc.setE (res.getString (5));
        sc.setF (res.getInt (6));
        sc.setG (res.getString (7));
        sc.setH (res.getByte (8)); // the exception is thrown here
    }
    stmt.close ();
    conn.commit ();
    if (sc != null) {
        // do some processing that involves loading other records from the
        // DB using the same connection
    }
}
conn.close();

Vấn đề nằm ở phần "thực hiện một số xử lý liên quan đến việc tải các bản ghi khác từ DB bằng cách sử dụng cùng một kết nối", thật không may, tôi đã không đưa vào câu hỏi ban đầu của mình, vì tôi không nghĩ rằng vấn đề là ở đó.

Phóng to phần đó, chúng ta có:

if (sc != null) {
    ...
    someMethod (conn);
    ...
}

someMethod trông như thế này:

public void someMethod (Connection conn) 
{
    ...
    SomeOtherClass instance = new SomeOtherClass (conn);
    ...
}

SomeOtherClass trông như thế này (tất nhiên tôi đang đơn giản hóa ở đây):

public class SomeOtherClass
{
    Connection conn;

    public SomeOtherClass (Connection conn) 
    {
        this.conn = conn;
    }

    protected void finalize() throws Throwable
    { 
        if (this.conn != null)
            conn.close();
    }

}

SomeOtherClass có thể tạo kết nối DB của riêng nó trong một số trường hợp, nhưng có thể chấp nhận kết nối hiện có trong các trường hợp khác, như kết nối chúng tôi có ở đây.

Như bạn có thể thấy, Phần đó chứa lệnh gọi đến someMethod chấp nhận kết nối mở làm đối số. someMethod chuyển kết nối đến một phiên bản cục bộ của SomeOtherClass . SomeOtherClass có một finalize phương thức đóng kết nối.

Bây giờ, sau someMethod trả về, instance trở nên đủ điều kiện để thu gom rác. Khi nó được thu gom rác, finalize phương thức được gọi bởi luồng thu gom rác, luồng này sẽ đóng kết nối.

Bây giờ chúng ta quay lại vòng lặp for, tiếp tục thực hiện các câu lệnh SELECT bằng cách sử dụng cùng một kết nối có thể bị đóng bởi luồng thu gom rác bất kỳ lúc nào.

Nếu chuỗi bộ thu gom rác tình cờ đóng kết nối trong khi chuỗi ứng dụng đang ở giữa một số phương thức trình kết nối mysql dựa vào kết nối để mở, một NullPointerException có thể xảy ra.

Xóa finalize phương pháp đã giải quyết vấn đề.

Chúng tôi không thường ghi đè finalize trong các lớp của chúng tôi, điều này khiến việc xác định lỗi rất khó khăn.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. MySQL trong đó cột ='x, y, z'

  2. Cách sử dụng thẻ JSTL sql

  3. Làm cách nào để tạo truy vấn UNION với ORDER BY và GROUP BY trong trình tạo truy vấn của Kohana?

  4. MySQL - Chọn dữ liệu từ nhiều bảng có cùng cấu trúc nhưng dữ liệu khác nhau

  5. node.js async / await sử dụng với MySQL