Koneksi ke Database Membuat Database

advertisement
Koneksi ke Database
Jika anda ingin mengakses ke database, Anda bisa menggunakan JDBC (Java
Database Connectivity). JDBC merupakan salah satu API (Application Programming
Interface) Java yang secara khusus ditujukan untuk menangani koneksi ke database.
Keunggulan antarmuka ini adalah memungkinkan programmer menulis sebuah
program yang dapat digunakan untuk mengakses database yang berbeda-beda;
misalnya Oracle, Access, dan MySQL.
Kode JSP
JDBC
Driver
(Oracle)
Driver
(ODBC)
Driver
(MySQL)
Database
Server
Oracle
Database
Server
Oracle
Database
Server
MySQL
Membuat Database
Dalam proyek aplikasi web, biasanya dalam database terdapat beberapa tabel,
dimana menurut aturan relational database menyatakan bahwa satu tabel dengan
tabel lainnya dapat dihubungkan oleh sebuah kunci unik atau primer (primary key).
Dalam contoh ini kita membutuhkan 4 buah tabel yang relasinya seperti pada
gambar berikut:
Tabel album
Tabel album_artis
* id_album
* id_album
judul album
* nomor
tahun_rilis
id_artis
Tabel artis
Tabel isi_album
* id_album
* id_artis
* nomor
nama
judul_lagu
tahun_lahir
biodata
Buat database musik dengan 4 buah tabel dimana struktur dari masing-masing tabel
tersebut adalah sebagai berikut:
Tabel Artis
Field
Type
Length
id_artis
varchar
25
nama
varchar
25
tgl_lahir
date
biodata
text
Extra
Primary

Tabel Album
Field
Type
Length
id_album
varchar
25
judul_album
varchar
25
tahun
int
4
Extra
Primary

Tabel album_artis
Field
Type
Length
Extra
Primary
id_album
varchar
25

nomor
int
2

id_artis
varchar
25
isi_album
Field
Type
Length
Extra
Primary
id_album
varchar
25

nomor
int
2

judul_lagu
varchar
25
Mengakses Database Melalui JSP
Setelah Anda membuat database dan tabel-tabel yang diperlukan, maka sekarang
saatnya Anda mempelajari dasar-dasar pemrograman database dengan JDBC.
Pertama kali yang perlu diketahui adalah sejumlah interface yang tersedia pada
paket java.sql. Beberapa interface dapat dilihat pada tabel berikut:
Interface untuk koneksi database
Interface
Keterangan
Connection
Mendefinisikan koneksi ke database.
Driver
Mendefinisikan driver yang digunakan untuk melakukan
koneksi
ke
suatu
database.
Kelas
yang
mengimplementasikan interface ini juga terdapat pada paket
java.sql dengan nama DriverManager.
Statement
Mendefinisikan sejumlah metode yang berhubungan dengan
SQL.
ResultSet
Interface yang mendefinisikan pengaksesan hasil pernyataan
SQL.
Berikut ini adalah contoh cara membentuk koneksi ke database MySQL dengan
menggunakan database musik.
Nama file: teskoneksi.jsp
<HTML>
<HEAD>
<TITLE>Tes Koneksi Database</TITLE>
</HEAD>
<BODY>
<%@ page import="java.sql.Connection,
java.sql.DriverManager" %>
<%
boolean ada_kesalahan = false;
try {
Class.forName("com.mysql.jdbc.Driver");
}
catch (Exception ex) {
out.println("Kesalahan: " + ex);
ada_kesalahan = true;
}
if (!ada_kesalahan) {
//Bentuk koneksi
Connection koneksi = null;
try {
koneksi = DriverManager.getConnection(
"jdbc:mysql://localhost/dbAlumni", "root", "telogodhog");
out.println("Koneksi berhasil");
}
catch (Exception ex) {
out.println("Kesalahan: " + ex);
}
}
%>
</BODY>
</HTML>
Keterangan:
Dokumen
teskoneksi.jsp
menggunakan
interface
DriverManager. Oleh karena itu terdapat instruksi:
<%@ page import="java.sql.Connection,
java.sql.DriverManager" %>
Pernyataan:
try {
Class.forName("com.mysql.jdbc.Driver");
}
catch (Exception ex) {
out.println("Kesalahan: " + ex);
ada_kesalahan = true;
}
Connection
dan
kelas
digunakan untuk memuat driver MySQL (yaitu MySQL Connector/J). Jika terjadi
suatu eksepsi maka bagian berikut akan dijalankan
out.println("Kesalahan: " + ex);
ada_kesalahan = true;
Pada pernyataan di atas, baris pertama akan menampilkan pesan kesalahan dan
baris berikutnya mengisi variabel ada_kesalahan yang bertipe boolean dengan nilai
true, yang menyatakan terjadi kesalahan.
Pernyataan:
Connection koneksi = null;
digunakan untuk mendeklarasikan variabel koneksi yang merujuk ke objek
Connection dan sekaligus mengisinya dengan null.
Pernyataan:
try {
koneksi = DriverManager.getConnection(
"jdbc:mysql://localhost/dbAlumni", "root", "telogodhog");
out.println("Koneksi berhasil");
}
catch (Exception ex) {
out.println("Kesalahan: " + ex);
}
digunakan untuk membuat koneksi ke database MySQL dengan nama database
dbAlumni yang terdapat di localhost, menggunakan username “root” dan
password telogodhog. String berikut::
“jdbc:mysql://localhost/musik”
disebut dengan URL (Universal Resource Locator). Secara umum, penulisan sebuah
URL untuk JDBC adalah sebagai berikut:
jdbc:subprotokol:subnama
Pada contoh di atas, karena database server yang diakses adalah MySQL maka
subprotokol diisi dengan MySQL. Misalnya:
//localhost/musik
menyebutkan nama host (localhost) dan nama database (musik).
Pada pernyataan try di atas, bagian:
out.println(“Kesalahan: ” + ex);
dijalankan
kalau
terjadi
eksepsi
pada
saat
DriverManager.getConnection
dieksekusi.
Menampilkan Record Tabel
Dengan dasar script sebelumnya, bisa dikembangkan program yang lebih kompleks
lagi untuk menampilkan isi tabel artis yang terdapat pada database musik. Script nya
adalah sebagai berikut:
Nama file: tesdb.jsp
<HTML>
<HEAD>
<TITLE>Tes Database</TITLE>
</HEAD>
<BODY>
<%@ page import="java.sql.Connection,
java.sql.DriverManager,
java.sql.Statement,
java.sql.ResultSet" %>
<%
boolean ada_kesalahan = false;
try {
Class.forName("com.mysql.jdbc.Driver");
}
catch (Exception ex) {
out.println("Kesalahan: " + ex);
ada_kesalahan = true;
}
if (!ada_kesalahan) {
//Bentuk koneksi
Connection koneksi = null;
try {
koneksi = DriverManager.getConnection(
"jdbc:mysql://localhost/musik",
"root", "telogodhog");
}
catch (Exception ex) {
out.println("Kesalahan: " + ex);
ada_kesalahan = true;
}
if (!ada_kesalahan) {
ResultSet hasilQuery = null;
try {
Statement stm = koneksi.createStatement();
hasilQuery = stm.executeQuery("SELECT id_artis, nama, tahun_lahir " +
"FROM artis " + "ORDER BY nama");
}
catch (Exception ex) {
out.println("Kesalahan: " + ex);
ada_kesalahan = true;
}
if (!ada_kesalahan) {
out.println("<TABLE BORDER=\"1\">");
out.println(
"<TR><TH>ID</TH><TH>NAMA</TH>" +
"<TH>TAHUN LAHIR</TH></TR>");
try {
while (hasilQuery.next()) {
String id =
hasilQuery.getString("id_artis");
String nama =
hasilQuery.getString("nama");
String tahun =
hasilQuery.getString("tahun_lahir");
out.println("<TR><TD>" + id +
"</TD><TD>" + nama +
"</TD><TD>" + tahun +
"</TD></TR>");
}
}
catch (Exception ex) {
out.println("Kesalahan: " + ex);
}
out.println("</TABLE>");
}
}
}
%>
</BODY>
</HTML>
Penjelasan:
Pada dokumen tesdb.jsp, pernyataan:
ResultSet hasilQuery = null;
digunakan untuk mendeklarasikan variabel hasilQuery yang merujuk objek
ResulSet. Variabel tersebut diberi nilai awal null.
Pada script tersebut juga terdapat pernyataan:
try {
Statement stm = koneksi.createStatement();
hasilQuery = stm.executeQuery("SELECT id_artis, nama, tahun_lahir " +
"FROM artis " + "ORDER BY nama");
}
catch (Exception ex) {
out.println("Kesalahan: " + ex);
ada_kesalahan = true;
}
digunakan untuk membuat variabel stm yang merujuk ke objek Statement dan
variabel ini merujuk ke hasil dari createStatement() (objek yang digunakan untuk
melakukan query). Kemudian:
hasilQuery = stm.executeQuery("SELECT id_artis, nama, tahun_lahir " +
"FROM artis " + "ORDER BY nama");
merupakan perintah SQL untuk menjalankan pernyataan SQL:
SELECT id_artis, nama, tahun_lahir FROM artis ORDER BY nama
Pernyataan SQL tersebut digunakan untuk memperoleh data id_artis, nama, dan
tahun_lahir yang terdapat pada tabel artis dan hasilnya diurutkan berdasarkan
nama. Hasilnya akan dirujuk oleh variabel hasilQuery.
Jika salah satu dari kedua pernyataan di atas menimbulkan eksepsi, maka bagian
berikut akan dijalankan:
catch (Exception ex) {
out.println("Kesalahan: " + ex);
ada_kesalahan = true;
}
Pernyataan try berikutnya digunakan untuk menampilkan hasil query. Pernyataan:
while (hasilQuery.next()) {
digunakan untuk melakukan pengulangan selama data yang belum dibaca pada hasil
query masih ada. Jika masih ada maka akan dilakukan langkah seperti berikut:
1. Memperoleh data id_artis, melalui pernyataan:
String id =
hasilQuery.getString("id_artis");
2. Memperoleh data nama, melalui pernyataan
String nama =
hasilQuery.getString("nama");
3. Memperoleh tahun lahir, lelalui pernyataan
String tahun =
hasilQuery.getString("tahun_lahir");
4. Menampilkan isi variabel id_artis, nama, dan tahun
out.println("<TR><TD>" + id +
"</TD><TD>" + nama +
"</TD><TD>" + tahun +
"</TD></TR>");
Kalau terdapat eksepsi, maka pernyataan berikut akan dijalankan:
catch (Exception ex) {
out.println("Kesalahan: " + ex);
}
Pengaksesan Data Pada Tabel
Dokumen berikut memperlihatkan contoh pengaksesan data pada tabel album dan
isi_album berdasarkan id_album yang berasal dari parameter.
Nama file: infoalbum.jsp
<HTML>
<HEAD>
<TITLE>Info Album</TITLE>
</HEAD>
<BODY>
<%@ page import="java.sql.Connection,
java.sql.DriverManager,
java.sql.Statement,
java.sql.ResultSet,
java.io.File" %>
<%
boolean ada_kesalahan = false;
String arg_id_album = request.getParameter("id");
if (arg_id_album == null) {
out.println("Tidak ada kode album yang diberikan");
ada_kesalahan = true;
}
if (!ada_kesalahan) {
try {
Class.forName("com.mysql.jdbc.Driver");
}
catch (Exception ex) {
out.println("Kesalahan: " + ex);
ada_kesalahan = true;
}
}
if (!ada_kesalahan) {
//bentuk koneksi
Connection koneksi = null;
try {
koneksi = DriverManager.getConnection(
"jdbc:mysql://localhost/musik",
"root", "telogodhog");
}
catch (Exception ex) {
out.println("Kesalahan: " + ex);
ada_kesalahan = true;
}
if (!ada_kesalahan) {
ResultSet hasilQuery = null;
try {
Statement stm = koneksi.createStatement();
String strQuery = "SELECT * FROM album " +
"WHERE id_album = \'" +
arg_id_album + "\'";
hasilQuery = stm.executeQuery(strQuery);
}
catch (Exception ex) {
out.println("Kesalahan: " + ex);
ada_kesalahan = true;
}
try {
if (!hasilQuery.next()) {
out.println("Tak ada yang memenuhi");
ada_kesalahan = true;
}
}
catch (Exception ex) {
out.println("Kesalahan: " + ex);
ada_kesalahan = true;
}
if (!ada_kesalahan) {
//tampilkan gambar
//String berkasFoto =
// getServletContext().getRealPath("/")+
// "/image/" +
// arg_id_album.toLowerCase() + ".jpg";
//File berkas = new File(berkasFoto);
//if (berkas.exists())
out.println(
"<IMG SRC = " + "image/" + arg_id_album.toLowerCase() + ".jpg"
+ ">");
//tampilkan info
String judul =
hasilQuery.getString("judul_album");
String tahun =
hasilQuery.getString("tahun_rilis");
out.println("<H2>" + judul + ":</H2><BR>");
out.println("<B>Tahun rilis: </B>" +
tahun + "<BR><BR>");
out.println("<B>Isi Album:</B><BR>");
//Baca data album
try {
Statement stm = koneksi.createStatement();
String strQuery = "SELECT * FROM isi_album " +
"WHERE id_album = \'" +
arg_id_album + "\'" +
" ORDER BY nomor";
hasilQuery = stm.executeQuery(strQuery);
out.println("<TABLE BORDER = \"1\">");
while (hasilQuery.next()) {
String judul_lagu =
hasilQuery.getString("judul_lagu");
int nomor =
hasilQuery.getInt("nomor");
out.println("<TR><TD>" + nomor +
"</TD><TD>" + judul_lagu +
"</TD></TR>");
}
}
catch (Exception ex) {
out.println("Kesalahan: " + ex);
ada_kesalahan = true;
}
out.println("</TABLE>");
}
}
}
%>
</BODY>
</HTML>
Penjelasan:
Pada dokumen di atas, kode:
String arg_id_album = request.getParameter("id");
digunakan untuk memperoleh isi parameter dengan nama id. Isi parameter ini
digunakan untuk melakukan query terhadap database.
Pernyataan:
String strQuery = "SELECT * FROM album " +
"WHERE id_album = \'" +
arg_id_album + "\'";
digunakan untuk membentuk string query berdasarkan isi variabel arg_id_album
(yang berisi isi dari parameter id). Tanda \' digunakan untuk menyertakan tanda petik
tunggal di depan dan di belakang nilai variabel arg_id_album.
Pernyataan:
out.println("<IMG SRC = " + "image/" + arg_id_album.toLowerCase() +
".jpg" + ">");
digunakan untuk menampilkan foto melalui tag HTTP bernama IMG lengkap dengan
dengan nama direktori tempat foto berada. Metode toLowerCase() digunakan untuk
mengkonversi ke huruf kecil.
Pernyataan:
String strQuery = "SELECT * FROM isi_album " +
"WHERE id_album = \'" +
arg_id_album + "\'" +
" ORDER BY nomor";
digunakan untuk membentuk string query yang dipakai untuk mengakses data pada
tabel isi_album. Dalam hal ini hasil query diurutkan menurut field nomor.
Berikut adalah contoh hasil pengaksesan terhadap dokumen infoalbum.jsp yang
dilakukan dengan memberikan URL:
http://localhost:8080/latihan/infoalbum.jsp?id=melayang
Dokumen berikut memperlihatkan contoh pengaksesan data pada tabel artis
berdasarkan id_artis yang berasal dari parameter dan kemudian menampilkan data
lengkap dari artis yang bersangkutan dan juga semua album yang pernah dirilis.
Nama file: infoalbum.jsp
<HTML>
<HEAD>
<TITLE>Info Artis</TITLE>
</HEAD>
<BODY>
<%@ page import="java.sql.Connection,
java.sql.DriverManager,
java.sql.Statement,
java.sql.ResultSet,
java.sql.Clob,
java.io.File" %>
<%
boolean ada_kesalahan = false;
String arg_id_artis = request.getParameter("id");
if (arg_id_artis == null) {
out.println("Tidak ada kode artis yang diberikan");
ada_kesalahan = true;
}
if (!ada_kesalahan) {
try {
Class.forName("com.mysql.jdbc.Driver");
}
catch (Exception ex) {
out.println("Kesalahan: " + ex);
ada_kesalahan = true;
}
}
if (!ada_kesalahan) {
//bentuk koneksi
Connection koneksi = null;
try {
koneksi = DriverManager.getConnection(
"jdbc:mysql://localhost/musik",
"root", "telogodhog");
}
catch (Exception ex) {
out.println("Kesalahan: " + ex);
ada_kesalahan = true;
}
if (!ada_kesalahan) {
ResultSet hasilQuery = null;
try {
Statement stm = koneksi.createStatement();
String strQuery = "SELECT * FROM artis " +
"WHERE id_artis = \'" +
arg_id_artis + "\'";
hasilQuery = stm.executeQuery(strQuery);
}
catch (Exception ex) {
out.println("Kesalahan: " + ex);
ada_kesalahan = true;
}
try {
if (!hasilQuery.next()) {
out.println("Tak ada yang memenuhi");
ada_kesalahan = true;
}
}
catch (Exception ex) {
out.println("Kesalahan: " + ex);
ada_kesalahan = true;
}
if (!ada_kesalahan) {
//tampilkan gambar
//String berkasFoto =
// getServletContext().getRealPath("/")+
// "/image/" +
// arg_id_album.toLowerCase() + ".jpg";
//File berkas = new File(berkasFoto);
//if (berkas.exists())
out.println(
"<IMG SRC = " + "image/" + arg_id_artis.toLowerCase() + ".jpg" +
">");
//tampilkan info
String id_artis =
hasilQuery.getString("id_artis");
String nama =
hasilQuery.getString("nama");
String tahun =
hasilQuery.getString("tahun_lahir");
Clob keterangan =
hasilQuery.getClob("biodata");
out.println("<H2>" + nama + ":</H2><BR>");
out.println("<B>Tahun lahir: </B>" +
tahun + "<BR><BR>");
if (keterangan != null)
out.println("<B>Riwayat Singkat:</B><BR>" +
keterangan.getSubString(1,
(int)keterangan.length()) +
"<BR><BR>");
else
out.println("<B>Riwayat Singkat:</B><BR>" +
"Tidak tercatat<BR><BR>");
out.println("<B>Album:</B><BR>");
//Baca data album
try {
Statement stm = koneksi.createStatement();
String strQuery =
"SELECT a.* " +
"FROM album a, album_artis b " +
"WHERE a.id_album = b.id_album AND " +
"b.id_artis = \'" +
arg_id_artis + "\'" +
" ORDER BY a.tahun_rilis";
hasilQuery = stm.executeQuery(strQuery);
while (hasilQuery.next()) {
String id_album =
hasilQuery.getString("a.id_album");
String judul_album =
hasilQuery.getString("a.judul_album");
String tahun_rilis =
hasilQuery.getString("a.tahun_rilis");
out.println(
"<A HREF = \"infoalbum.jsp?id=" +
id_album + "\" TARGET = \"dinamis\">" +
judul_album +
"</A> (" + tahun_rilis + ")<BR>");
}
}
catch (Exception ex) {
out.println("Kesalahan: " + ex);
ada_kesalahan = true;
}
}
}
}
%>
</BODY>
</HTML>
Penjelasan:
Pada dokumen di atas, kode:
String arg_id_artis = request.getParameter("id");
digunakan untuk memperoleh isi parameter dengan nama id. Isi parameter ini
digunakan untuk melakukan query terhadap database.
Pernyataan:
String strQuery = "SELECT * FROM artis " +
"WHERE id_artis = \'" +
arg_id_artis + "\'";
digunakan untuk membentuk string query berdasarkan isi variabel arg_id_artis
(yang berisi isi dari parameter id). Tanda \' digunakan untuk menyertakan tanda petik
tunggal di depan dan di belakang nilai variabel arg_id_artis.
Pernyataan:
Clob keterangan =
hasilQuery.getClob("biodata");
digunakan untuk memperoleh field biodata yang bertipe text (teks yang sangat
panjang). Hasilnya diletakkan pada variabel bernama keterangan yang bertipe Clob
(tipe untuk mengakses data bertipe text).
Selanjutnya, data pada variabel keterangan ditampilkan melalui:
keterangan.getSubString(1,
(int)keterangan.length())
Pernyataan:
String strQuery =
"SELECT a.* " +
"FROM album a, album_artis b " +
"WHERE a.id_album = b.id_album AND " +
"b.id_artis = \'" +
arg_id_artis + "\'" +
" ORDER BY a.tahun_rilis";
digunakan untuk membentuk string query yang digunakan untuk mengakses data
pada data album yang merupakan data dari artis yang sesuai dengan parameter id.
Pernyataan:
out.println(
"<A HREF = \"infoalbum.jsp?id=" +
id_album + "\" TARGET = \"dinamis\">" +
judul_album +
"</A> (" + tahun_rilis + ")<BR>");
dipakai untuk membentuk link ke infoalbum.jsp. Atribut TARGET = “dinamis”
digunakan untuk keperluan penggunaan frame.
Dokumen berikut digunakan untuk menampilkan semua nama artis dan menyertakan
link ke dokumen infoartis.jsp.
Nama file: daftarartis.jsp
<HTML>
<HEAD>
<TITLE>Daftar Artis</TITLE>
</HEAD>
<BODY>
<%@ page import="java.sql.Connection,
java.sql.DriverManager,
java.sql.Statement,
java.sql.ResultSet" %>
<%
boolean ada_kesalahan = false;
if (!ada_kesalahan) {
try {
Class.forName("com.mysql.jdbc.Driver");
}
catch (Exception ex) {
out.println("Kesalahan: " + ex);
ada_kesalahan = true;
}
}
if (!ada_kesalahan) {
//bentuk koneksi
Connection koneksi = null;
try {
koneksi = DriverManager.getConnection(
"jdbc:mysql://localhost/musik",
"root", "telogodhog");
}
catch (Exception ex) {
out.println("Kesalahan: " + ex);
ada_kesalahan = true;
}
if (!ada_kesalahan) {
ResultSet hasilQuery = null;
try {
Statement stm = koneksi.createStatement();
hasilQuery = stm.executeQuery("SELECT id_artis, nama FROM artis "
+
"ORDER BY nama");
}
catch (Exception ex) {
out.println("Kesalahan: " + ex);
ada_kesalahan = true;
}
if (!ada_kesalahan) {
try {
while (hasilQuery.next()) {
String id_artis =
hasilQuery.getString("id_artis");
String nama =
hasilQuery.getString("nama");
out.println(
"<A HREF = \"infoartis.jsp?id=" +
id_artis +
"\" TARGET = \"dinamis\">" +
nama + "</A><BR>");
}
}
catch (Exception ex) {
out.println("Kesalahan: " + ex);
}
}
}
}
%>
</BODY>
</HTML>
Pembuatan Frame
Nama file: info.htm
<HTML>
<HEAD>
<TITLE>Informasi Group Band Indonesia</TITLE>
</HEAD>
<FRAMESET ROWS = "30%, *">
<FRAME SRC = "judul.htm" SCROLLING = "NO">
<FRAMESET BORDER = "0" COLS = "30%, *">
<FRAME SRC = "daftarartis.jsp">
<FRAME SRC = "petunjuk.htm" NAME = "dinamis">
</FRAMESET>
</FRAMESET>
</HTML>
Penjelasan:
Dokumen di atas membentuk tiga buah area (frame). Bagian atas, menyita ruang
sebesar 30%, akan ditempati oleh dokumen judul.htm. Bagian bawahnya dibagi dua
secara vertikal. Bagian kiri akan ditempati oleh daftarartis.jsp dan bagian kanan
ditempati oleh petunjuk.htm. Bagian kiri menempati ruang sebesar 30% dan
sisanya untuk frame bagian kanan. Atribut SCROLLING = “NO” digunakan untuk
membuat frame bagian atas tidak dilengkapi dengan batang penggeser. Atribut
NAME = “dinamis” dipakai untuk menyatakan bahwa frame yang ditempati
petunjuk.htm diberi nama “dinamis”. Nama inilah yang dirujuk oleh TARGET =
“dinamis” pada dokumen daftarartis.jsp dan infoartis.jsp. Artinya frame tersebut
akan dijadikan lokasi untuk menampilkan dokumen yang disebut pada tag <A>.
Sebelum mencoba file info.htm, lengkapi dulu dengan dua dokumen berikut.
Nama file: info.htm
<HTML>
<HEAD><TITLE></TITLE></HEAD>
<BODY>
<CENTER><H3>Group Band Indonesia</H3></CENTER>
<CENTER>
<IMG SRC = "band.jpg">
</CENTER>
</BODY>
</HTML>
Penjelasan:
Dokumen di atas menampilkan file gambar band.jpg.
Nama file: info.htm
<HTML>
<HEAD><TITLE></TITLE></HEAD>
<CENTER>
Silakan klik pada nama-nama
yang tertera di samping untuk
memperoleh info masing-masing artis
</CENTER>
</BODY>
</HTML>
Download