Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

NullPointerException sesekali di ResultSetImpl.checkColumnBounds atau ResultSetImpl.getStringInternal

Sudah lama sejak saya memposting pertanyaan ini, dan saya ingin memposting jawaban yang menjelaskan skenario persis yang menyebabkan NullPointerException yang rumit ini .

Saya pikir ini dapat membantu pembaca masa depan yang menemukan pengecualian yang membingungkan untuk berpikir di luar kebiasaan, karena saya memiliki hampir semua alasan untuk mencurigai ini adalah bug konektor mysql, meskipun sebenarnya tidak.

Saat menyelidiki pengecualian ini, saya yakin bahwa aplikasi saya tidak mungkin menutup koneksi DB saat mencoba membaca data darinya, karena koneksi DB saya tidak dibagikan di seluruh utas, dan jika utas yang sama menutup koneksi dan kemudian mencoba mengakses itu, pengecualian yang berbeda seharusnya dilemparkan (beberapa SQLException ). Itulah alasan utama saya mencurigai adanya bug konektor mysql.

Ternyata ada dua thread mengakses koneksi yang sama Lagipula. Alasan mengapa hal ini sulit diketahui adalah karena salah satu utas ini adalah utas pengumpul sampah .

Kembali ke kode yang saya posting:

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

Masalahnya terletak pada bagian "lakukan beberapa pemrosesan yang melibatkan pemuatan catatan lain dari DB menggunakan koneksi yang sama", yang, sayangnya, tidak saya sertakan dalam pertanyaan awal saya, karena saya pikir masalahnya tidak ada di sana.

Memperbesar bagian itu, kami memiliki:

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

Dan someMethod terlihat seperti ini:

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

SomeOtherClass terlihat seperti ini (tentu saja saya sederhanakan di sini):

public class SomeOtherClass
{
    Connection conn;

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

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

}

SomeOtherClass dapat membuat koneksi DB sendiri dalam beberapa skenario, tetapi dapat menerima koneksi yang ada dalam skenario lain, seperti yang kita miliki di sini.

Seperti yang Anda lihat, Bagian itu berisi panggilan ke someMethod yang menerima koneksi terbuka sebagai argumen. someMethod meneruskan koneksi ke instance lokal SomeOtherClass . SomeOtherClass telah finalize metode yang menutup koneksi.

Sekarang, setelah someMethod kembali, instance memenuhi syarat untuk pengumpulan sampah. Saat sampah dikumpulkan, finalize metode ini dipanggil oleh utas pengumpul sampah, yang menutup koneksi.

Sekarang kita kembali ke loop for, yang terus mengeksekusi pernyataan SELECT menggunakan koneksi yang sama yang dapat ditutup kapan saja oleh thread pengumpul sampah.

Jika utas pengumpul sampah menutup koneksi saat utas aplikasi berada di tengah beberapa metode konektor mysql yang bergantung pada koneksi untuk dibuka, NullPointerException mungkin terjadi.

Menghapus finalize metode memecahkan masalah.

Kami tidak sering mengganti finalize metode di kelas kami, yang membuatnya sangat sulit untuk menemukan bug.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Konfigurasikan server email agar berfungsi dengan PHP

  2. Mysql:Tidak diizinkan untuk mengembalikan set hasil dari suatu fungsi

  3. MySQL di Cloud - Migrasi Online Dari Amazon RDS ke Instans EC2:Bagian Satu

  4. Memahami Pernyataan dan Parameter Pengikatan yang Disiapkan PDO

  5. Semua kolom disetel ke nilai yang sama