JTable bisa dikatakan primadona di Java Swing karena sebagai komponen yang bertugas untuk menampilkan data di database dalam bentuk tabel maka dia akan sering digunakan. Selain itu, penggunaannya yang relatif lebih sulit dibandingkan komponen lain membuatnya memiliki perhatian tersendiri. Kali ini kita akan bermain-main dengan JTable supaya bisa mendukung fitur pagination.
Pagination atau kadang disebut juga paging adalah teknik untuk menampilkan data yang dibuat berhalaman-halaman, jadi tidak semua data yang ada ditumpahkan blek pada satu halaman. Ada beberapa alasan kenapa diterapkannya teknik tersebut, setidaknya ada 3 alasan bagi saya
1. Jika jumlah data besar, katakanlah 300 data maka akan tidak efisien jika semuanya ditampilkan dalam satu halaman. User akan malas dan kesulitan jika harus scroll terus kebawah.
2. Jika data sangat besar dan terus bertambah dan untuk menampilkan data kita taruh terlebih dahulu di memory maka cepat atau lambat akan mengalami OOM (Out of Memory) karena memory tidak mampu lagi menampung data yang besar tersebut.
3. Alasan ketiga agak tidak mutu jadi bolehlah dikesampingkan yaitu jika menggunakan pagination akan terlihat keren dan canggih.
Untuk memudahkan mengikuti tutorial ini maka saya sertakan stuktur proyek pada Netbeans sebagai berikut
Struktur Database
Berikut adalah struktur dari tabel pelanggan yang digunakan sebagai contoh
1 2 3 4 5 6 7 8 9 |
CREATE TABLE `pelanggan` ( `id` int(11) NOT NULL AUTO_INCREMENT, `nama_depan` varchar(50) NOT NULL, `nama_belakang` varchar(50) NOT NULL, `email` varchar(32) NOT NULL, `telepon` varchar(32) NOT NULL, `tanggal_daftar` datetime NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=latin1 |
Kelas Domain
Kita buat kelas domain untuk tabel pelanggan diatas seperti dibawah ini
file : src/main/java/com/agungsetiawan/jtablepagination/domain/Pelanggan.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
package com.agungsetiawan.jtablepagination.domain; import java.util.Date; /** * * @author awanlabs */ public class Pelanggan { private Long id; private String namaDepan; private String namaBelakang; private String email; private String telepon; private Date tanggalDaftar; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getNamaDepan() { return namaDepan; } public void setNamaDepan(String namaDepan) { this.namaDepan = namaDepan; } public String getNamaBelakang() { return namaBelakang; } public void setNamaBelakang(String namaBelakang) { this.namaBelakang = namaBelakang; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getTelepon() { return telepon; } public void setTelepon(String telepon) { this.telepon = telepon; } public Date getTanggalDaftar() { return tanggalDaftar; } public void setTanggalDaftar(Date tanggalDaftar) { this.tanggalDaftar = tanggalDaftar; } } |
Kelas Service
Untuk proses menarik data dari database perlu kita buat sebuah kelas tersendiri untuk menanganinya. Disini kita membuat sebuah kelas dengan nama PelangganService untuk menangani penarikan data tersebut.
Ketikkan kode dibawah ini
file : src/main/java/com/agungsetiawan/jtablepagination/service/PelangganService.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
package com.agungsetiawan.jtablepagination.service; import com.agungsetiawan.jtablepagination.domain.Pelanggan; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import javax.sql.DataSource; /** * * @author awanlabs */ public class PelangganService { private Connection connection; private PreparedStatement preparedStatement; private DataSource dataSource; public void setDataSource(DataSource dataSource){ this.dataSource=dataSource; } public List<Pelanggan> findAll(int halaman,int banyakBaris){ List<Pelanggan> listPelanggan=new ArrayList<Pelanggan>(); try{ connection=dataSource.getConnection(); connection.setAutoCommit(false); preparedStatement=connection.prepareStatement("SELECT * FROM pelanggan limit ?,?"); preparedStatement.setInt(1, banyakBaris*(halaman-1)); preparedStatement.setInt(2, banyakBaris); ResultSet rs=preparedStatement.executeQuery(); while(rs.next()){ Pelanggan p=new Pelanggan(); p.setId(rs.getLong("id")); p.setNamaDepan(rs.getString("nama_depan")); p.setNamaBelakang(rs.getString("nama_belakang")); p.setEmail(rs.getString("email")); p.setTelepon(rs.getString("telepon")); p.setTanggalDaftar(rs.getDate("tanggal_daftar")); listPelanggan.add(p); } connection.commit(); connection.setAutoCommit(true); }catch(SQLException ex){ ex.printStackTrace(); try{ connection.rollback(); }catch(SQLException exRollBack){ exRollBack.printStackTrace(); } }finally{ try{ connection.close(); }catch(SQLException exClose){ exClose.printStackTrace(); } return listPelanggan; } } public int count(){ int jumlahBaris=0; try{ connection=dataSource.getConnection(); connection.setAutoCommit(false); preparedStatement=connection.prepareStatement("SELECT count(id) from pelanggan"); ResultSet rs=preparedStatement.executeQuery(); while(rs.next()){ jumlahBaris=rs.getInt("count(id)"); } connection.commit(); connection.setAutoCommit(true); }catch(SQLException ex){ ex.printStackTrace(); try{ connection.rollback(); }catch(SQLException exRollBack){ exRollBack.printStackTrace(); } }finally{ try{ connection.close(); }catch(SQLException exClose){ exClose.printStackTrace(); } return jumlahBaris; } } } |
Terdapat 2 method pada kelas diatas. Method pertama digunakan untuk mengambil data dari database dengan menggunakan query limit untuk membatasi jumlah data yang diambil. Method kedua berfungsi menghitung jumlah data yang ada pada tabel pelanggan.
Table Model
Langkah selanjutnya kita buat sebuah table model sebagai model data untuk JTable yang akan kita gunakan nanti. Buat sebuah kelas PelangganTableModel
file : src/main/java/com/agungsetiawan/tablemodel/SiswaTableModel.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
package com.agungsetiawan.jtablepagination.tablemodel; import com.agungsetiawan.jtablepagination.domain.Pelanggan; import java.util.ArrayList; import java.util.List; import javax.swing.table.AbstractTableModel; /** * * @author awanlabs */ public class PelangganTableModel extends AbstractTableModel{ List<Pelanggan> listPelanggan=new ArrayList<Pelanggan>(); private final String HEADER[]={"Nama Depan","Nama Belakang","Email","Telepon","Tanggal Daftar"}; public void setList(List<Pelanggan> listPelanggan){ this.listPelanggan=listPelanggan; } public void save(Pelanggan pelanggan){ listPelanggan.add(pelanggan); fireTableRowsInserted(getRowCount()-1, getRowCount()-1); } public void edit(int index,Pelanggan pelanggan){ listPelanggan.set(index, pelanggan); fireTableRowsUpdated(index, index); } public void delete(int index){ listPelanggan.remove(index); fireTableRowsDeleted(index, index); } public Pelanggan findOne(int index){ return listPelanggan.get(index); } public int getRowCount() { return listPelanggan.size(); } public int getColumnCount() { return HEADER.length; } public String getColumnName(int column){ return HEADER[column]; } public Object getValueAt(int rowIndex, int columnIndex) { Pelanggan pelanggan=listPelanggan.get(rowIndex); switch(columnIndex){ case 0: return pelanggan.getNamaDepan(); case 1: return pelanggan.getNamaBelakang(); case 2: return pelanggan.getEmail(); case 3: return pelanggan.getTelepon(); case 4: return pelanggan.getTanggalDaftar(); default: return null; } } } |
Desain Form
Desain Form sesuka hati, kalau saya mendesain seperti pada gambar dibawah
Untuk mengetahui komponen apa saja yang ada serta nama variabelnya berikut keterangannya
Kelas Form
Modifikasi kode pada kelas FormPelanggan. Tambahkan beberapa variabel serta ubah constructor seperti pada kode dibawah ini.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
PelangganTableModel pelangganTableModel; Integer nomorHalaman=1; Integer jumlahBarisPerhalaman=5; Integer totalHalaman=1; Integer totalData=0; public FormPelanggan() { initComponents(); setLocationRelativeTo(null); jComboBoxJumlahBaris.addItem("5"); jComboBoxJumlahBaris.addItem("15"); jComboBoxJumlahBaris.addItem("30"); jComboBoxJumlahBaris.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { initPagination(); } }); initPagination(); } |
initPagination() adalah private method, dibawah ini adalah body-nya
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
private void initPagination(){ totalData=App.getPelangganService().count(); jumlahBarisPerhalaman=Integer.valueOf(jComboBoxJumlahBaris.getSelectedItem().toString()); Double totalHalamanD=Math.ceil(totalData.doubleValue()/jumlahBarisPerhalaman.doubleValue()); totalHalaman=totalHalamanD.intValue(); if(nomorHalaman.equals(1)){ jButtonFirst.setEnabled(false); jButtonPrevious.setEnabled(false); }else{ jButtonFirst.setEnabled(true); jButtonPrevious.setEnabled(true); } if(nomorHalaman.equals(totalHalaman)){ jButtonLast.setEnabled(false); jButtonNext.setEnabled(false); }else{ jButtonLast.setEnabled(true); jButtonNext.setEnabled(true); } if(nomorHalaman>totalHalaman){ nomorHalaman=1; } pelangganTableModel=new PelangganTableModel(); pelangganTableModel.setList(App.getPelangganService().findAll(nomorHalaman, jumlahBarisPerhalaman)); jTablePelanggan.setModel(pelangganTableModel); jLabelStatusHalaman.setText("Halaman "+nomorHalaman+" dari "+totalHalaman); jLabelTotalData.setText(("Total data "+totalData)); } |
Tambahkan aksi klik pada keempat tombol navigasi
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
private void jButtonFirstActionPerformed(java.awt.event.ActionEvent evt) { nomorHalaman=1; initPagination(); } private void jButtonPreviousActionPerformed(java.awt.event.ActionEvent evt) { if(nomorHalaman>1){ nomorHalaman--; initPagination(); } } private void jButtonNextActionPerformed(java.awt.event.ActionEvent evt) { if(nomorHalaman<totalHalaman){ nomorHalaman++; initPagination();; } } private void jButtonLastActionPerformed(java.awt.event.ActionEvent evt) { nomorHalaman=totalHalaman; initPagination(); } |
Kelas Launcher
Kelas App kita gunakan sebagai launcher yaitu kelas yang pertama dijalankan untuk menampilkan menu utama program. Karena bertindak sebagai launcher maka kita harus menuliskan method main disini, dan berikut ini adalah isi dari kelas App.
file : src/main/java/com/agungsetiawan/jtablepagination/App.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
package com.agungsetiawan.jtablepagination; import com.agungsetiawan.jtablepagination.service.PelangganService; import com.agungsetiawan.jtablepagination.ui.FormPelanggan; import com.jtattoo.plaf.mint.MintLookAndFeel; import com.mysql.jdbc.jdbc2.optional.MysqlDataSource; import javax.swing.UIManager; /** * Hello world! * */ public class App{ private static PelangganService pelangganService; public static PelangganService getPelangganService(){ return pelangganService; } public static void main( String[] args ){ MysqlDataSource dataSource=new MysqlDataSource(); dataSource.setUser("root"); dataSource.setPassword(""); dataSource.setDatabaseName("jtablepagination"); dataSource.setServerName("localhost"); pelangganService=new PelangganService(); pelangganService.setDataSource(dataSource); try{ UIManager.setLookAndFeel(new MintLookAndFeel()); new FormPelanggan().setVisible(true); }catch(Exception ex){ ex.printStackTrace(); } } } |
Screenshot
Eksekusi kelas App dan berikut adalah screenshot dari proyek yang kita buat.
Penutup
Jika ada kesulitan mengikuti tutorial ini dan atau jika kode diatas masih ada kekurangan yok diskusikan bersama melalui fitur komentar 🙂
Class MysqlDataSource – nya mana bro ?
Maaf mas agung saya ada kendala saat mengikuti tutorial ini, kalo untuk membuat project baru emang si berhasil mengikuti tutorial ini.. tapi masalahnya, saya sudah punya service dan juga CRUD’nya sendiri, dan kendala saya adalah saat ingin menerapkan paging ini di internalframe yg saya punya, error, ga bisa dipanggil internalframe’nya kira-kira masalahnya dimana ya.. udah 3 hari ni mas, tolong di bantu mas agung. terima kasih sebelumnya..
mantap.. thanks a lot