Ada banyak diskusi di dunia internet terutama Stackoverflow mengenai teknik penyimpanan gambar pada basisdata. Diskusi yang umum terjadi adalah apakah akan menyimpan gambar langsung dalam basisdata sebagai sebuah binary menggunakan tipe data Blob atau gambar disimpan di file system (biasanya folder) dan pada basisdata hanya menyimpan path/nama file gambar dalam tipe varchar.
Kedua teknik tadi memiliki pros dan cons masing-masing. Silahkan ikuti diskusinya disini untuk mengetahuinya. Pada kesempatan kali ini saya akan menunjukkan cara menyimpan sebuah gambar di basisdata pada aplikasi java swing menggunakan teknik yang kedua, yaitu hanya menyimpan nama file dari gambar.
Struktur Project dan Library yang Digunakan
Untuk memudahkan memahami tutorial ini berikut adalah struktur project pada Netbeans serta library yang digunakan
untuk media penyimpanan file gambar kita buat sebuah folder dengan nama [rad-hl]image[/rad-hl] yang terletak sejajar dengan folder [rad-hl]src[/rad-hl]
Diagram Use Case
Diagram fungsional dibawah ini menunjukkan apa saja yang bisa dilakukan oleh pengguna aplikasi.
Menyiapkan Basisdata
Buat sebuah basisdata dengan sebuah tabel bernama [rad-hl]book[/rad-hl]
1 2 3 4 5 6 |
CREATE TABLE `book` ( `id` int(11) NOT NULL AUTO_INCREMENT, `title` varchar(50) NOT NULL, `image` varchar(100) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=35 DEFAULT CHARSET=latin1 |
Kelas Domain
Jangan lupa untuk membuat sebuah kelas domain yang merepresentasikan tabel book yang baru saja kita buat. Kelas ini memiliki properti yang sama dengan kolom pada tabel book.
file : Book.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 |
package com.agungsetiawan.saveimagedb.domain; /** * * @author awanlabs */ public class Book { private Integer id; private String title; private String image; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getImage() { return image; } public void setImage(String image) { this.image = image; } } |
Kelas DAO
Kelas DAO berfungsi untuk melakukan operasi dengan basisdata. Jadi semua hal yang berhubungan dengan basisdata kita serahkan ke DAO ini seperti simpan, ambil, ubah dan hapus data.
Pada aplikasi yang kita buat DAO hanya memiliki 2 method untuk operasi basisdata yaitu untuk menyimpan buku dan mendapatkan daftar buku yang telah disimpan.
file : BookDao.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 |
package com.agungsetiawan.saveimagedb.dao; import com.agungsetiawan.saveimagedb.domain.Book; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; /** * * @author awanlabs */ public class BookDao { Connection connection; PreparedStatement preparedStatement; public void setConnection(Connection connection){ this.connection=connection; } public void save(Book book) throws SQLException{ preparedStatement=connection.prepareStatement("insert into book(title,image) values(?,?)"); preparedStatement.setString(1, book.getTitle()); preparedStatement.setString(2, book.getImage()); preparedStatement.executeUpdate(); } public List<Book> findAll() throws SQLException{ List<Book> listOfBook=new ArrayList<Book>(); preparedStatement=connection.prepareStatement("select * from book"); ResultSet rs=preparedStatement.executeQuery(); while(rs.next()){ Book book=new Book(); book.setId(rs.getInt("id")); book.setTitle(rs.getString("title")); book.setImage(rs.getString("image")); listOfBook.add(book); } return listOfBook; } } |
Kelas Service
Service digunakan sebagai logika bisnis aplikasi. Selain itu service juga digunakan sebagai tempat mengatur transaksi pada basisdata. Jika transaksi berhasil maka transaksi akan dicommit, jika gagal transaksi akan di rollback untuk dikembalikan seperti semula.
Lebih lengkap soal transaksi baca disini
file : BookService.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 |
package com.agungsetiawan.saveimagedb.service; import com.agungsetiawan.saveimagedb.dao.BookDao; import com.agungsetiawan.saveimagedb.domain.Book; import com.mysql.jdbc.jdbc2.optional.MysqlDataSource; import java.sql.Connection; import java.sql.SQLException; import java.util.List; /** * * @author awanlabs */ public class BookService { Connection connection; BookDao bookDao; public BookService(MysqlDataSource dataSource) throws SQLException{ this.connection=dataSource.getConnection(); bookDao=new BookDao(); bookDao.setConnection(connection); } public void save(Book book){ try{ connection.setAutoCommit(false); bookDao.save(book); connection.commit(); connection.setAutoCommit(true); } catch(SQLException exception){ try { connection.rollback(); } catch (SQLException ex) { ex.printStackTrace(); } } } public List<Book> findAll(){ try { return bookDao.findAll(); } catch (SQLException ex) { ex.printStackTrace(); } return null; } } |
Table Model
Kalau saya perhatikan masih banyak yang menggunakan [rad-hl]DefaultTableModel[/rad-hl] untuk menampilkan data di JTable. Padahal kalau dibandingkan dengan teknik yang akan saya gunakan jauh lebih gampang menggunakan ini nantinya. Konsentrasi penanganan kode untuk menampilkan data dan manipulasi lainnya di JTable seperti update, delete, edit hanya terfokus pada kelas ini.
Table model yang selalu saya gunakan merupakan sub-kelas dari [rad-hl]AbstractTableModel[/rad-hl]
file : BookTableModel.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 |
package com.agungsetiawan.saveimagedb.tablemodel; import com.agungsetiawan.saveimagedb.domain.Book; import java.util.ArrayList; import java.util.List; import javax.swing.table.AbstractTableModel; /** * * @author awanlabs */ public class BookTableModel extends AbstractTableModel{ List<Book> listOfBook=new ArrayList<Book>(); private final String[] header={"Judul","Nama Gambar"}; public BookTableModel(List<Book> listOfBook){ this.listOfBook=listOfBook; } public void save(Book book){ listOfBook.add(book); fireTableRowsInserted(getRowCount()-1, getRowCount()-1); } public Book findOne(int index){ return listOfBook.get(index); } @Override public int getRowCount() { return listOfBook.size(); } @Override public int getColumnCount() { return header.length; } @Override public String getColumnName(int column){ return header[column]; } @Override public Object getValueAt(int rowIndex, int columnIndex) { Book book=listOfBook.get(rowIndex); switch(columnIndex){ case 0:return book.getTitle(); case 1:return book.getImage(); default:return null; } } } |
Desain Form
Desainlah form pada Netbeans GUI Builder seperti pada gambar dibawah ini atau sesuaikan dengan selera
Berikut ini nama variabel komponen dari GUI diatas
Kode pada Form
Tambahkan beberapa deklarasi objek diatas constructor dan ubah constructor menjadi seperti berikut
file : UploadImageFrame.java
1 2 3 4 5 6 7 8 9 |
BookService bookService; BookTableModel bookTableModel; File file; JFileChooser jfc; public UploadImageFrame() { initComponents(); initTable(); } |
disitu terlihat adanya method tambahan [rad-hl]initTable()[/rad-hl]. Method ini digunakan untuk mengisi JTable dengan data yang tersimpan pada basisdata saat pertama kali form muncul. Selain itu pada method ini juga terdapat kode untuk memunculkan gambar pada kotak jlabel ketika salah satu data di JTable terseleksi.
Dibawah ini adalah isi dari initTable(), letakkan dibawah constructor
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 |
private void initTable(){ jTableBook.getSelectionModel().addListSelectionListener(new ListSelectionListener() { @Override public void valueChanged(ListSelectionEvent e) { try { int row=jTableBook.getSelectedRow(); Book book=bookTableModel.findOne(row); Toolkit toolkit=Toolkit.getDefaultToolkit(); String path=new File(".").getCanonicalPath(); Image image=toolkit.getImage(path+"/image/"+book.getImage()); //mengambil gambar dari folder image Image imagedResized=image.getScaledInstance(200, 250, Image.SCALE_DEFAULT); //resize foto sesuai ukuran jlabel ImageIcon icon=new ImageIcon(imagedResized); jLabelGambar.setIcon(icon); // memasang gambar pada jlabel } catch (IOException ex) { Logger.getLogger(UploadImageFrame.class.getName()).log(Level.SEVERE, null, ex); } } }); bookService=SaveImageDB.getBookService(); bookTableModel=new BookTableModel(bookService.findAll()); //mengisi table model dengan data di basisdata jTableBook.setModel(bookTableModel); } |
Dari row yang terseleksi pada jtable kita bisa memperoleh baris keberapa yang terseleksi dengan menggunakan
int row=jTableBook.getSelectedRow();
dari situ kita bisa mendapatkan objek book dengan memanfaatkan kelas tabel model sebagai berikut
Book book=bookTableModel.findOne(row);
Dari objek book maka bisa kita dapatkan nama file gambar buku yang tersimpan pada database. Untuk meloadnya digunakan
Image image=toolkit.getImage(path+”/image/”+book.getImage());
Dan kemudian diresize yang akhirnya ditampilkan pada jlabel
Semoga cukup jelas penjelasannya
Tombol cari buku digunakan untuk browsing gambar pada hardisk komputer yang akan digunakan sebagai gambar pelengkap data buku. Berikut adalah event kliknya
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
private void jButtonPilihGambarActionPerformed(java.awt.event.ActionEvent evt) { jfc=new JFileChooser(); if(jfc.showOpenDialog(jLabelGambar)==JFileChooser.APPROVE_OPTION){ Toolkit toolkit=Toolkit.getDefaultToolkit(); Image image=toolkit.getImage(jfc.getSelectedFile().getAbsolutePath()); Image imagedResized=image.getScaledInstance(200, 250, Image.SCALE_DEFAULT); ImageIcon imageIcon=new ImageIcon(imagedResized); jLabelGambar.setIcon(imageIcon); jLabelNamaFileBuku.setText(jfc.getSelectedFile().getName()); file=new File(jfc.getSelectedFile().getPath()); // file untuk dikopi } } |
Pada method diatas perhatikan pada baris yang saya tandai. Objek tersebut digunakan untuk menampung file gambar yang nantinya akan dikopikan kedalam folder image ketika proses penyimpanan data.
Terakhir adalah membuat event simpan pada tombol simpan. Pada proses penyimpanan akan berlangsung pula proses penyalinan gambar dari folder asli dimana gambar tersebut berasal menuju folder [rad-hl]image[/rad-hl] yang telah kita buat tadi, untuk itulah library [rad-hl]apache commons io[/rad-hl] digunakan.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
private void jButtonSimpanGambarActionPerformed(java.awt.event.ActionEvent evt) { Book book=new Book(); book.setTitle(jTextFieldTitle.getText()); book.setImage(jLabelNamaFileBuku.getText()); bookService.save(book); bookTableModel.save(book); try { String path=new File(".").getCanonicalPath(); FileUtils.copyFileToDirectory(file, new File(path+"/image")); //copy file ke folder image } catch (IOException ex) { Logger.getLogger(UploadImageFrame.class.getName()).log(Level.SEVERE, null, ex); } } |
Pada baris yang saya tandai. Semudah itulah menyalin file menggunakan library apache commons io 😀
Kelas Main
Modifikasi kelas utama kita menjadi seperti ini
file : SaveImageDB.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 |
package saveimagedb; import com.agungsetiawan.saveimagedb.service.BookService; import com.agungsetiawan.saveimagedb.ui.UploadImageFrame; import com.mysql.jdbc.jdbc2.optional.MysqlDataSource; import java.sql.SQLException; /** * * @author awanlabs */ public class SaveImageDB { private static BookService bookService; public static BookService getBookService(){ return bookService; } public static void main(String[] args) throws SQLException { MysqlDataSource dataSource=new MysqlDataSource(); dataSource.setUser("root"); dataSource.setPassword(""); dataSource.setServerName("localhost"); dataSource.setDatabaseName("saveimagedb"); bookService=new BookService(dataSource); new UploadImageFrame().setVisible(true); } } |
Screenshot
SS gambar dikopi pada folder image
SS gambar akan muncul sesuai dengan data yang terseleksi
Source Code
Source Code bisa didownload pada Github saya disini
Jangan lupa untuk menambahkan library yang dibutuhkan
Ketika aplikasi kita sudah berbentuk .jar jangan lupa untuk membuat folder [rad-hl]image[/rad-hl] untuk menyimpan gambar sejajar dengan file .jar aplikasi kita

Semoga bermanfaat 🙂
Jika ada yang kurang jelas saya persilahkan untuk bertanya
Mas untuk ImagesDb.jar ada gak?
Mas, “FileUtils” di saya kok terbaca error di netbeans, ini menyangkut ke library ekstensi atau kita harus membuat class baru FileUtils?
itu harus download library dulu mas,, apache common io download terus tambahin ke library
Mas makasih banged.. sangat membantu,, selama ini saya tidak pernah pake DAO pake… langsung work mas..
makasih…jadi seru nih kepoin blog nya…
FileUtils puxa sy tdk terdeteksi jg…erornya disebabkan itu…
mas boleh bagi source code untuk update n delete nya?soalnya saya udah nyoba tapi gak mau kesimpen di database…please
Maaf Mas Aris, saya sudah tidak menyimpan source codenya
Cara login ke github kok susah bngt
Maskalo misalkan saya membuat aplikasi kyak gitu terus udah sya jadikan file jar,lha untuk menjalankan aplikasi tersebut kan harus menyalakan mysqlnya dulu pada komoputer kita dari xampp, dan yang saya tanyakan,
Bagaimana jika kita ingin mnjalankanan aplikasi yang sudah saya buat tnpa harus menjalankan mysqlnya (jika kita mnjalankan aplikasinya, mysql otomatis nyala, tnpa harus mnyalakan mysql dari xampp), terima kasih.
jalankan mysql lewat perintah teks (command line) pas program pertama jalan Mas, konsepnya seperti itu.
Contohnya bisa dilihat di sini http://dev.mysql.com/doc/refman/5.7/en/windows-start-command-line.html
Itu di XAMPP, tombol start MySql di belakangnya juga melakukan hal yang sama
Ok mas, terima kasih
untuk media penyimpanan file gambar kita buat sebuah folder dengan nama [rad-hl]image[/rad-hl] yang terletak sejajar dengan folder [rad-hl]src[/rad-hl]
MAKSUDNYA APA?