Saya memiliki masalah dengan kode saya, program saya mengisi formulir JTable DB MySQL menggunakan utas, program berfungsi dengan baik tetapi saya mendapatkan kesalahan ini

//Error, com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Sumber data menolak pembuatan koneksi, pesan dari server: "Terlalu banyak koneksi" Kesalahan java.lang.NullPointerException//

Saya pikir saya perlu menutup koneksi atau mungkin tidak menggunakan Thread untuk mengisi JTable, ide saya itu mengisi tabel tanpa menggunakan acara JButton, apakah Anda punya saran untuk ini?

public class VentanaAdministrador extends javax.swing.JFrame{

    public static final String URL = "jdbc:mysql://localhost:3306/floreria?autoReconnet=true&useSSL=false";
    public static final String Usuario = "root";
    public static final String Contraseña = "";
    PreparedStatement ps;
    ResultSet rs;
    
    public Connection getConnection(){
        Connection conexion = null;
        
        try{
            Class.forName("com.mysql.jdbc.Driver");
            conexion = (Connection) DriverManager.getConnection(URL,Usuario,Contraseña);
        }catch(Exception ex){
            System.err.println("Error, "+ex);
        }
        
        return conexion;
    }
    ///////////////////////////////////////////////
    Thread llenado = new Thread(){
        public void run(){
        DefaultTableModel modeloTabla = new DefaultTableModel();
        TablaVentanaAsignar.setModel(modeloTabla);
        
        PreparedStatement ps = null;
        ResultSet rs = null;
        
        
        try{
            VentanaAdministrador con = new VentanaAdministrador();
            Connection VentanaAdministrador = con.getConnection();
            
            ps = VentanaAdministrador.prepareStatement("select NumeroEmpleado,Nombre,Punto_de_venta,TiempoTrabajo from empleados where Puesto=?");
            ps.setString(1, "Diseñador");
            rs = ps.executeQuery();
            
            modeloTabla.addColumn("No. Empleado");
            modeloTabla.addColumn("Nombre");
            modeloTabla.addColumn("Sucursal");
            modeloTabla.addColumn("Tiempo trabajado");
            
            while(rs.next()){
                Object fila[] = new Object[4];
                fila[0] = rs.getObject(1);
                fila[1] = rs.getObject(2);
                fila[2] = rs.getObject(3);
                fila[3] = rs.getObject(4);
                
                modeloTabla.addRow(fila);
            }   
            }catch(Exception ex){
                    System.err.println("Error "+ex);
                    
        }
        }
    };    
    
    public VentanaAdministrador() {
        initComponents();
        llenado.start();
    }
2
Mario Garcia 12 Mei 2021, 06:53

1 menjawab

Jawaban Terbaik

Umumnya terbaik dalam pekerjaan database untuk fokus melakukan hal berikut secepat dan langsung praktis:

  • (a) terhubung ke database,
  • (b) menjalankan kueri,
  • (c) mengambil data, dan
  • (d) mengakhiri koneksi (atau mengembalikan koneksi ke pool jika Anda menggunakan connection-pooling).

Jadi tidak perlu membawa PreparedStatement dan ResultSet sebagai bidang anggota di kelas Anda seperti yang terlihat dalam kode Anda. Objek tersebut harus cepat dipakai, digunakan, dan dibuang (secara umum).

Pisahkan database Anda bekerja dari GUI berfungsi. Berinteraksi dengan database bisa memakan waktu cukup lama, jadi jalankan itu di utas latar belakang. Setelah selesai, gunakan titik akses yang sesuai di GUI Anda untuk memintanya memperbarui widgetnya dengan data baru — tetapi memperbarui sendiri dalam rangkaian GUI-nya sendiri. Jangan pernah mengakses widget GUI dari utas lain. Apakah Anda menggunakan JavaFX/OpenJFX< /a>, Swing, SWT, Vaadin Alur, atau Android, setiap kerangka kerja GUI memiliki kaitan untuk meminta GUI perbarui widgetnya di utas GUI sendiri.

Di Java modern, kita jarang perlu mengalamatkan kelas Thread secara langsung. Untuk pekerjaan bersamaan, gunakan kerangka kerja Pelaksana yang ditambahkan ke Java 5.

Anda akan mendapatkan fleksibilitas maksimal dalam pengembangan, pengujian, dan penerapan jika Anda menggunakan DataSource antarmuka untuk memuat info koneksi daripada sekadar string seperti yang terlihat dalam kode Anda. Biasanya driver JDBC menyediakan implementasi dasar DataSource. Misalnya, Connector/J menyediakan kelas com.mysql.cj.jdbc.MysqlDataSource.

private DataSource prepareDataSource() {
    MysqlDataSource ds = new com.mysql.cj.jdbc.MysqlDataSource();
    ds.setServerName( "1.2.3.4" );
    ds.setPortNumber( 5432 );
    ds.setUser( "scott" );
    ds.setPassword( "tiger") ;
    ds.setDatabaseName( "invoicing" );
    … Set all your relevant properties …
    return ds ;
}

Simpan DataSource ini di tempat yang praktis dalam aplikasi Anda, untuk digunakan oleh kode apa pun yang memerlukan koneksi database.

Juga siapkan implementasi ExecutorService yang akan digunakan untuk pekerjaan threading latar belakang Anda. Gunakan Executors kelas utilitas untuk mendapatkan instance dengan mudah. Pastikan untuk akhirnya mematikan layanan eksekutor sebelum aplikasi Anda keluar, karena kumpulan utas pendukungnya dapat terus berjalan tanpa batas seperti zombie.

ExecutorService executorService = Executors.newFixedThreadPool( 3 ) ;

Atau, di masa mendatang ketika teknologi Project Loom tiba:

ExecutorService executorService = Executors.newVirtualThreadExecutor() ;

Gunakan sintaks coba-dengan-sumber daya saat melakukan pekerjaan JDBC. Ini menyederhanakan kode Anda dengan cara yang bermanfaat, secara otomatis menutup sumber daya database Anda.

Tentukan pekerjaan database Anda sebagai objek tugas yang mengimplementasikan rel Runnable (atau Callable) antarmuka. Kirimkan sebuah instance ke layanan eksekutor Anda.

/// Code in your GUI detects need to load data.
/// … Fetch the `ExecutorService` from wherever you stored it.
executorService.submit( new DatabaseWorkRunnable() ) ;

run metode Runnable itu mungkin terlihat seperti kode yang tidak lengkap dan belum teruji seperti di bawah ini.

Perhatikan bagaimana kode ini memiliki sepasang pernyataan try-with-resources yang mencakup tiga AutoCloseable objek sumber daya: Connection, PreparedStatement, dan ResultSet. Jika dipakai, setiap objek sumber daya akan ditutup apakah kode Anda berhasil diselesaikan atau tidak. Sumber daya ditutup dalam urutan terbalik di mana mereka dideklarasikan.

Objek DataSource bukan sumber daya dan tidak pernah "terbuka". Jadi tidak pernah ditutup. DataSource hanya menyimpan informasi untuk membuka koneksi ke database.

String sql = "SELECT … ;";
try (
        Connection conn = dataSource.getConnection() ;
        PreparedStatement ps = conn.prepareStatement( sql ) ;
)
{
    … Make `PreparedStatement::set…` calls here.
    try (
            ResultSet rs = ps.executeQuery() ;
    )
    {
        if ( rs.next() )
        {
            LocalDate ld = rs.getObject( 1 , LocalDate.class );
            … Retrieve your data , add to collection to be delivered to GUI later.
        }
    }
}
catch ( SQLException e )
{
    e.printStackTrace();
}
// At this point, all three `Connection`, `PreparedStatement`, and `ResultSet` objects are closed automatically whether your code ran successfully or whether an exception/error was thrown.

… Use your GUI framework’s hook to ask the GUI to update its table widget with the fresh data in collection. 

Semua ini telah dibahas berkali-kali di Stack Overflow. Telusuri untuk mempelajari lebih lanjut dan lihat banyak contoh.

3
Basil Bourque 12 Mei 2021, 21:38