JVA-FD-09003 – MENGAKSES DATABASE DENGAN JDBC 1
MENGAKSES DATABASE DENGAN JDBC
November 2009 Tingkat: √
Oleh : Feri Djuandi Pemula Menengah Mahir
Pendahuluan
Agar sebuah program Java dapat mengakses database, dibutuhkan sebuah antar muka aplikasi yang disebut Java Database Connectivity (JDBC). JDBC driver adalah sebuah komponen yang menjembatani komunikasi antara program Java dengan database dalam hal pengiriman perintah-perintah SQL maupun pengembalian hasil-hasilnya. JDBC sangat serupa dengan ODBC driver yang dikenal pada program-program di lingkungan Windows yang berfungsi untuk melakukan hal di atas.
Pada masa ini ada banyak system database (disebut juga DMBS atau Database Management System) yang beredar di pasaran seperti SQL Server, Oracle, DB-2, MySQL, Postgree dan masih banyak lagi. Setiap DBMS memiliki JDBC driver yang berbeda-beda untuk setiap penggunaannya. Misalnya JDBC driver untuk SQL Server hanya dapat digunakan untuk mengakses DBMS tersebut dan tidak bisa digunakan untuk mengakses database lain (Oracle misalnya) karena protocol komunikasi setiap DBMS berbeda-beda. Umumnya setiap pengembang DBMS menyediakan JDBC driver yang bisa di-download secara gratis oleh penggunanya, namun ada pula pengembang pihak ke-tiga yang membuat sendiri JDBC driver yang berbayar dan menawarkan beberapa kelebihan.
Untuk mendapatkan informasi lebih lengkap mengenai JDBC, silakan membaca artikel di situs web: http://en.wikipedia.org/wiki/JDBC_driver.
Terlepas dari DBMS dan JDBC driver yang digunakan, umumnya tidak ada banyak perbedaan di dalam sebuah program Java dalam hal penggunaan class-class yang berkaitan dengan operasi database (java.sql.*) karena class-class tersebut bersifat generik dan tidak terkait secara khusus pada DBMS tertentu. Jadi sebuah program Java yang sama dapat dengan mudah dialihkan dari satu DBMS ke DMBS lain dengan memodifikasi parameter koneksinya.
Contoh-contoh program yang diperlihatkan pada artikel ini akan menggunakan Ms SQL Server. Untuk JDBC drivernya, penulis menggunakan komponen bernama jTDS yang dapat dipakai untuk SQL Server versi 6.5 hingga 2008. JDBC driver untuk SQL Server ini dapat di-download gratis dari situs web: http://jtds.sourceforge.net/
JVA-FD-09003 – MENGAKSES DATABASE DENGAN JDBC 2 Setelah driver tersebut berhasil diperoleh, silakan mengikuti langkah-langkah berikut ini untuk mulai membuat sebuah contoh program.
1. Jalankan Eclipse dan buat sebuah project baru.
2. Beri nama project tersebut sebagai db-exercise01. Klik Finish.
3. Buat sebuah Folder di dalam project yang baru dibuat dan beri nama lib.
4. Secara manual dengan menggunakan Windows Explorer, copy file jtds-1.2.4.jar yang di-download sebelumnya ke dalam folder lib yang ada di dalam folder project ini (di dalam folder workspace dari Eclipse).
JVA-FD-09003 – MENGAKSES DATABASE DENGAN JDBC 3 5. Lakukan konfigurasi pada Build Path untuk mengasosiasikan file JAR tersebut dengan project ini.
Pilih tab Libraries dan klik tombol “Add External JARs”.
JVA-FD-09003 – MENGAKSES DATABASE DENGAN JDBC 4 Saat selesai menambahkan library tersebut, struktur project akan tampak seperti gambar di bawah ini.
JVA-FD-09003 – MENGAKSES DATABASE DENGAN JDBC 5 7. Di dalam package tersebut, buat sebuah class bernama DbConnect. Secara bersamaan
tambahkan juga method main ke dalam class tersebut. Klik Finish.
Anda telah selesai membuat sebuah project dan class sebagai langkah persiapan. Silakan mengikuti bagian selanjutnya untuk tahap-tahap pembuatan contoh program.
JVA-FD-09003 – MENGAKSES DATABASE DENGAN JDBC 6
Membuat Koneksi ke Database
Hal pertama yang selalu dilakukan pertama kali saat mengakses sebuah database adalah membuat koneksi. Silakan membuka class DbConnect dan tambahkan baris-baris kode hingga seperti di bawah ini.
package org.exercise01.db;
import java.sql.*;
public class DbConnect {
public static void main(String[] args) {
final String JDBC_DRIVER = "net.sourceforge.jtds.jdbc.Driver";
final String DATABASE_URL = "jdbc:jtds:sqlserver://127.0.0.1/Northwind"; Connection connection = null; // manages connection
Statement statement = null; // query statement // connect to database and query
try
{
Class.forName( JDBC_DRIVER ); // load database driver class // establish connection to database
connection = DriverManager.getConnection( DATABASE_URL, "sa", "sql" ); System.out.println("Connection succeeds");
// create Statement for querying database
statement = connection.createStatement(); }
catch ( SQLException sqlException ) {
sqlException.printStackTrace(); System.exit( 1 );
}
catch ( ClassNotFoundException classNotFound ) {
classNotFound.printStackTrace(); System.exit( 1 );
}
finally // ensure statement and connection are closed properly
{ try { if (statement != null) statement.close(); if (connection != null) connection.close(); } catch (SQLException ex) { ex.printStackTrace(); System.exit( 1 ); } } } }
Silakan menjalankan program di atas. Jika tidak ada kesalahan, akan tampak tulisan “Connection succeeds” muncul pada layar.
Program di atas dapat dipahami secara mudah. Konstanta JDBC_DRIVER diisi dengan nama library dari JDBC driver yang digunakan, dalam hal ini adalah jDTS. Perhatikan bahwa nama library yang digunakan pada contoh ini adalah khusus untuk jDTS. Jika digunakan JDBC driver lain, maka nama library nya tentu akan berbeda pula karena setiap pengembang dapat menetapkan nama library nya sendiri. Agar dapat mengetahui nama library dari JDBC driver yang bersangkutan secara benar, maka dokumentasi yang menyertai driver tersebut harus dibaca baik-baik.
Untuk memastikan tidak ada kesalahan di dalam menuliskan nama library, umumnya di dalam program ditambahkan sebaris perintah untuk mem-verifikasi seperti berikut ini:
JVA-FD-09003 – MENGAKSES DATABASE DENGAN JDBC 7
...
Class.forName( JDBC_DRIVER ); ...
Konstanta DATABASE_URL berisi parameter koneksi ke database. Setiap DBMS memiliki format-format yang berbeda dalam hal menuliskan parameter ini. Sekali lagi, dokumentasi yang bersangkutan harus dibaca dengan baik.
Class java yang digunakan untuk membuat koneksi database adalah java.sql.Connection. Itu sebabnya pada awal program terdapat perintah “import java.sql.*;”. Perintah untuk membuat koneksi itu sendiri terdapat di dalam blok try yaitu pemanggilan fungsi getConnection yang sekaligus menginisiasi sebuah object Connection.
...
connection = DriverManager.getConnection( DATABASE_URL, "sa", "sql" ); ...
Sementara itu baris-baris kode lainnya yang ada di dalam blok catch adalah untuk penanganan error yang mungkin terjadi. Mereka adalah baris-baris kode “best practice” yang sebaiknya diikuti saja, walaupun programmer bebas untuk memodifikasinya.
Menjalankan Perintah SELECT
SELECT adalah perintah SQL yang sangat sering digunakan di dalam setiap operasi database. Untuk menjalankan perintah SELECT, ada dua class yang digunakan yaitu:
java.sql.Statement : untuk mempersiapkan perintah SQL java.sql.ResultSet : untuk menampung hasil perintah SELECT
Penggunaan kedua class tersebut diperlihatkan pada program di bawah ini dengan memodifikasi blok try.
. . .
try
{
Class.forName( JDBC_DRIVER ); // load database driver class
// establish connection to database
connection = DriverManager.getConnection( DATABASE_URL, "sa", "sql" );
// create Statement for querying database
statement = connection.createStatement();
// query database
ResultSet resultSet = statement.executeQuery(
"select EmployeeID,LastName,FirstName,Title from Employees;" );
// process query results
ResultSetMetaData metaData = resultSet.getMetaData();
int numberOfColumns = metaData.getColumnCount();
System.out.println( "Employee Table of Northwind Database:" );
for ( int i = 1; i <= numberOfColumns; i++ )
System.out.printf( "%-8s\t", metaData.getColumnName( i ) ); System.out.println();
while ( resultSet.next() ) {
for ( int i = 1; i <= numberOfColumns; i++ )
JVA-FD-09003 – MENGAKSES DATABASE DENGAN JDBC 8
System.out.println(); }
}
. . .
Pada program di atas tampak bahwa object Statement dibuat dari sebuah object Connection melalui method createStatement, dengan cara itu setiap perintah SQL diasosiasikan dengan sebuah koneksi database yang aktif. Sementara itu, object ResultSet dibentuk dari object Statement melalui method executeQuery. Sangat penting untuk memahami hubungan ketiga object ini yang pembentukannya dilakukan secara berurutan.
Setelah hasil eksekusi tertampung di dalam object RecordSet, selanjutnya isi kolom-kolom data dapat diperoleh melalui beberapa method berikut ini:
RecordSet.getObject: mengambil nilai kolom dalam tipe class Object RecordSet.getDate: mengambil nilai kolom dalam tipe class Date
RecordSet.getDouble: mengambil nilai kolom dalam tipe data standar double RecordSet.getFloat: mengambil nilai kolom dalam tipe data standar float RecordSet.getInt: mengambil nilai kolom dalam tipe data standar int RecordSet.getLong: mengambil nilai kolom dalam tipe data standar long RecordSet.getString: mengambil nilai kolom dalam tipe class String
Sebagai opsional, object ResultSetMetaData dapat dibentuk dari object RecordSet menggunakan method getMetaData yang tujuannya untuk mendapatkan informasi mengenai metadata dari RecordSet tersebut seperti jumlah kolom, nama-nama kolom, tipe-tipe data kolom dan sebagainya.
Menjalankan Perintah INSERT, UPDATE dan DELETE
Bila pada perintah SELECT, perintah SQL dijalankan menggunakan method Statement.executeQuery maka pada perintah INSERT, UPDATE dan DELETE, perintah SQL dijalankan menggunakan method Statement.executeUpdate. Method executeUpdate mengembalikan nilai bertipe int yang berisi jumlah baris data yang berhasil diproses dengan perintah tersebut.
Sangat penting untuk menjalankan perintah executeUpdate di dalam blok try agar jika terjadi kesalahan aliran program akan masuk ke dalam blok catch dan langkah penanganan dapat dilakukan atau pesan kesalahan dapat ditampilkan.
Lebih Lanjut dengan Isolasi Transaksi
Pada saat di dalam sebuah program terdapat beberapa kali pemanggilan method executeUpdate perlu dipertimbangkan apakah perintah-perintah SQL itu perlu dipersatukan di dalam sebuah transaksi. Sebuah transaksi merupakan serangkaian perintah-perintah SQL yang dianggap sebagai satu kesatuan. Jika sebuah perintah gagal, maka keseluruhan perintah itu harus dianggap batal – bahkan jika kesalahan itu terjadi di tengah rangkaian perintah maka perintah-perintah yang dijalankan sebelumnya juga harus dibatalkan dan seluruh keadaan harus kembali ke kondisi semula sebelum perintah dijalankan. Dengan kata lain, instruksi commit harus ditunda sampai seluruh rangkaian perintah berhasil dijalankan tanpa kesalahan.
JVA-FD-09003 – MENGAKSES DATABASE DENGAN JDBC 9 Hal tersebut bisa dilakukan dengan melakukan setting pada object Connection. Secara default object Connection memiliki opsi auto-commit yang bernilai TRUE yang artinya perintah commit dijalankan secara otomatis setiap kali perintah manipulasi data dilakukan. Opsi ini harus diubah menjadi FALSE jika skenario transaksi di atas akan diterapkan. Opsi auto-commit dapat diubah melalui method
Connection.setAutoCommit seperti yang ditunjukkan di bawah ini.
...
Connection connection = null; try
{
...
connection = DriverManager.getConnection( DATABASE_URL, "sa", "sql" ); connection.setAutoCommit(false); ... statement.executeUpdate(insertCommand); statement.executeUpdate(updateCommand); statement.executeUpdate(deleteCommand); ... connection.commit(); }
catch ( SQLException sqlException ) { connection.rollback(); sqlException.printStackTrace(); System.exit( 1 ); } ...
Konsekwensi akibat terbentuknya sebuah transaksi adalah terjadinya penguncian atau isolasi (locking atau transaction isolation) pada table-table yang bersangkutan. Isolasi sangat berpengaruh pada lingkungan multi-user dimana beberapa koneksi dapat secara bersamaan berusaha mengakses table yang sama namun pada satu saat hanya sebuah koneksi yang berhasil sementara koneksi-koneksi yang lain harus mengantri menunggu sampai kunci tersebut dilepaskan dan mengakses table tersebut secara bergantian. Isolasi ini jangan dipandang sebagai hal yang buruk tapi merupakan suatu konsekwensi logis untuk memastikan integritas dan konsistensi data (ACID= atomicity, consistency, isolation, durability). Namun di sisi lain isolasi juga akan mempengaruhi unjuk kerja sebuah program dimana program
tersebut terkesan lambat oleh karena ada waktu tunggu pada saat beberapa koneksi mengakses sebuah table secara bergantian. Namun kabar baiknya sampai dengan tahap tertentu tingkat isolasi ini masih bisa diatur mulai dari yang lemah (shared-lock) hingga ketat (exclusive-lock).
Pada program di atas tampak operasi database diakhiri dengan perintah Connection.commit saat semua transaksi berhasil dijalankan, namun jika terjadi kesalahan pada salah satu perintah SQL maka program akan lompat ke dalam blok catch dimana perintah Connection.rollback dijalankan dan membatalkan semua transaksi ke posisi awal. Inilah cara kerja isolasi transaksi database.
JVA-FD-09003 – MENGAKSES DATABASE DENGAN JDBC
Sebagai informasi tambahan, berikut ini adalah beberapa istilah yang perlu dipahami berkaitan dengan isolasi:
dirty read: sebuah transa lain sekalipun belum di-commit
commit, jika terjadi kesalahan dan terjadi rollback maka data yang dibaca tadi menjadi tidak valid.
phantom read atau repeatable read pembacaan data yang identik pembacaan itu terdapat
data itu tiba-tiba muncul secara misterius. non-repeatable read atau
kali perintah pembacaan data yang identik namun hasil yang dikembalikan berbeda karena di antara pembacaan itu terdapat
Tingkat isolasi dapat diatur melalui parameter Connection. setTransactionIsolation
tersebut diwakili dengan nilai konstanta
Tingkat Isolasi Connection. TRANSACTION_READ_UNCOMMITTED Connection. TRANSACTION_READ_COMMITTED Connection. TRANSACTION_REPEATABLE_READ Connection. TRANSACTION_SERIALIZABLE √ = diperbolehkan terjadi
x = tidak diperbolehkan terjadi Tampak dari table di atas bahwa
yang paling lemah, sementara TRANSACTION_SERIALIZABLE tidak ditetapkan, maka nilai default
masing DBMS dapat berbeda-beda. Informasi lebih lanjut mengenai http://en.wikipedia.org/wiki/ACID
http://en.wikipedia.org/wiki/Isolation_(database_systems)
MENGAKSES DATABASE DENGAN JDBC
, berikut ini adalah beberapa istilah yang perlu dipahami berkaitan dengan
transaksi membaca data dari sebuah baris yang telah diubah oleh
commit. Dikatakan dirty karena nilai data itu belum final sebab belum di commit, jika terjadi kesalahan dan terjadi rollback maka data yang dibaca tadi menjadi tidak
repeatable read: di dalam sebuah transaksi terdapat beberapa kali yang identik namun hasil yang dikembalikan berbeda karena di antara pembacaan itu terdapat transaksi lain yang menyisipkan data baru. Dikatakan
tiba muncul secara misterius.
atau inconsistent analysis: di dalam sebuah transaksi
kali perintah pembacaan data yang identik namun hasil yang dikembalikan berbeda karena di antara pembacaan itu terdapat transaksi lain yang merubah data yang ada
dapat diatur melalui parameter bertipe int yang dikirim ke dalam pemanggilan method Connection. setTransactionIsolation setelah perintah Connection.setAutoCommit(false)
konstanta sebagai berikut:
dirty reads TRANSACTION_READ_UNCOMMITTED √ Connection. TRANSACTION_READ_COMMITTED X TRANSACTION_REPEATABLE_READ X TRANSACTION_SERIALIZABLE X
Tampak dari table di atas bahwa isolasi menggunakan TRANSACTION_READ_UNCOMMITTED TRANSACTION_SERIALIZABLE adalah yang paling ketat.
tidak ditetapkan, maka nilai default-nya adalah tergantung dari setiap DBMS karena standar masing beda.
Informasi lebih lanjut mengenai isolasi bisa dibaca pada situs web: http://en.wikipedia.org/wiki/ACID
http://en.wikipedia.org/wiki/Isolation_(database_systems)
10 , berikut ini adalah beberapa istilah yang perlu dipahami berkaitan dengan
dari sebuah baris yang telah diubah oleh transaksi karena nilai data itu belum final sebab belum di-commit, jika terjadi kesalahan dan terjadi rollback maka data yang dibaca tadi menjadi tidak
terdapat beberapa kali perintah hasil yang dikembalikan berbeda karena di antara
Dikatakan phantom karena transaksi terdapat beberapa kali perintah pembacaan data yang identik namun hasil yang dikembalikan berbeda karena di
merubah data yang ada.
int yang dikirim ke dalam pemanggilan method setelah perintah Connection.setAutoCommit(false). Parameter
non-repeatable reads phantom reads √ √ √ √ X √ X X TRANSACTION_READ_UNCOMMITTED adalah adalah yang paling ketat. Jika tingkat isolasi dari setiap DBMS karena standar