Geçtiğimiz hafta boyunca, JBuilder ortamında
veritabanı uygulamalarının bileşenler yardımıyla kolay bir şekilde nasıl
oluşturulabileceğini inceledim. Bu hafta ise, temel tablo işlemlerini kod yazmak
suretiyle nasıl gerçekleştirebileceğimi araştırdım. JDBC oldukça geniş kapsama
sahip bir konuydu. Hatta geniş demek yetmez tam anlamıyla bir okyanus olduğunu
söyliyebilirim.
Nasıl ki Ado.Net hakkında yazılmış kalın, devasa kitaplar var
ise, JDBC içinde aynı durumun söz konusu olduğunu biliyordum. Ancak en azından
elimdeki kaynaklardan faydalanarak temel bir kaç tablo işleminin nasıl
gerçekleştirilebileceğinide incelem taraftarıydım. Bana gerekenler temel sql bilgisi
ve JDBC' nin bu işler için hangi sınıfları kullandığıydı. Sonuç olarak aşağıdaki
tarzda bir vizyon edinmeyi başarabildim. Basit bir veritabanı uygulaması için
gerekli unsurlar bunlardı. Bir JDBC sürücüsü, geçerli bir bağlantı, çalışan bir
sql cümleciği ve veri kümesini çekebileceğim bir bileşen.

Yapmam gereken son derece basitti. Uygulamam için
geçerli bir JDBC Driver' ı yükleyecek sonra bu driver'ı kullanarak, sistemdeki
odbc kaynaklarına bağlanabilecek bir Connection nesnesi oluşturacaktım. Daha
sonra bu Connection nesnesini kullanan bir Statement nesnesi yaratacak ve bu
nesneyi, tablodaki verileri çekmeme yardımcı olacak bir sql cümleciği ile
çalıştıracaktım. Statement nesnesi, Ado.Net' teki SqlCommand nesnesine çok
benziyordu. Her ikiside sql cümleciklerini çalıştırmak amacıyla
kullanılabiliyorlardı. Sql cümleciğinin çalıştırılması sonucu oluşacak veri kümesini
ise ResultSet sınıfından bir nesne örneğine aktaracaktım.
Bu düşünceler eşliğinde kahvemden bir yudum aldım
ve uzun süre monitore bakakaldım. Nitekim ne yapacağımı biraz olsun anlamama
rağmen nasıl yapacağımı henüz kestirememiştim. Elbetteki, kaynaklarım baş
ucumda duruyordu. Ancak özellikle JDBC ile ilgili olan kitaplar tam anlamıyla
kalın sayfa sayıları ile korkulu bir rüya gibiydiler. Kaynaklar arasında
geziniyor ve en basit haliyle nasıl geliştireceğimi araştırıyordum. O kitap bu
kitap derken uzun saatler sonrası bir şeyler çıkartmayı başarmıştım.
Bu araştırma
yaklaşık olarak 3 gün, geceli gündüzlü sürdürdüm. Geceleri biraz uyuduğumu
itiraf edeyim ama. Halen daha da tam olarak olaya
vakıf olabilmiş değildim. Ancak uygulamamı nasıl geliştirebileceğimi en azından
biliyordum. Hemen arkadaşımdan ödünç aldığım JBuilder Demo cd' si ile kurduğum
JBuilder uygulamasını açtım. Kodlarımı JBuilder üzerinde yazacaktım. Nitekim hem
tasarım ile az uğraşmak hemde JBuilder' ın intellisense özelliklerini kullanmak
istiyordum. Tabi JBuilder' ın geniş yardım içeriğide işin diğer cazip tarafıydı.
Öncelikle yeni bir Proje açtım, bu projeye bir Application ekledim ve temel
olarak aşağıdaki gibi bir Frame oluşturdum.

Uygulamada yapmak istediklerim ilk başta, Sql
sunucusunda yer alan Personel tablosundaki verileri ResultSet nesnesi içine
doldurmak ve sonra bu kayıt kümesindeki satırlar arasında navigasyon tuşları
yardımıyla gezinmekti. İlk olarak Doldur başlıklı button bileşenine basıldığında
çalışıtırılacak olay kodlarını yazdım.
public java.sql.ResultSet rsPersonel;
public java.sql.Connection conPersonel;
void btnDoldur_actionPerformed(ActionEvent e)
{
try
{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
conPersonel =
java.sql.DriverManager.getConnection( "jdbc:odbc:sqlBaglanti");
java.sql.Statement sqlPersonel =
conPersonel.createStatement(java.sql.ResultSet.TYPE_SCROLL_SENSITIVE,
java.sql.ResultSet.CONCUR_UPDATABLE);
rsPersonel =
sqlPersonel.executeQuery("SELECT * FROM Personel");
}
catch(Exception ex)
{
System.out.println(ex.getMessage());
}
} |
Burada yapılan işlemler şöyleydi. İlk olarak Class
sınıfının forName metodu ile, çalışacak uygulama thread' i için bir JDBC Driver'
ı yükleniyordu. Ben Sql sunucuma Odbc kaynakları üzerinden bağlanmak istediğim
için, JDBC' nin ODBC ile anlaşmasını sağlayacak bir driver' a ihtiyacım vardı.
İşte bu amaçla JdbcOdbcDriver' ını kullandım. Artık, uygulama çalıştığında ve
Doldur başlıklı butona basıldığında, ilk olarak bu uygulama için sisteme bir
JdbcOdbcDriver' ı yüklenecekti. Böylece, çalışan uygulama içinden bu Driver' ı
kullanarak ODBC kaynaklarına erişebilecektim. Bu erişimi sağlamak için ise
tabiki geçerli bir bağlantıya sahip olmam gerekiyordu. Bunu ise, java.sql
paketinde yer alan Connection sınıfı sayesinde gerçekleştirebilirdim.
| java.sql.Connection conPersonel =
java.sql.DriverManager.getConnection( "jdbc:odbc:sqlBaglanti"); |
Bu satır sayesinde, sisteme yüklediğim JDBC
driver' ını kullanan bir Connection bileşeni elde etmiş oluyordum. Bu Connection
bileşeni, ODBC kaynaklarında tanımladığım sqlBaglanti isimli System DSN' ini
kullanacaktı. Sonraki satır ise oldukça ilginçti.
| java.sql.Statement sqlPersonel =
conPersonel.createStatement(java.sql.ResultSet.TYPE_SCROLL_SENSITIVE,
java.sql.ResultSet.CONCUR_UPDATABLE); |
Nitekim burada, Sql
cümleciğini çalıştırabileceğim Ado.Net' teki SqlCommand tarzı bir bileşen
tanımlanıyordu. Bunun için java.sql paketinden, Statement sınıfı
kullanılıyordu. Statement bileşenini oluştururken iki parametre verdim. Bunlar
ResultSet sınıfına ait değerlerdi. Amacım uygulama içinde, elde ettiğim kayıt
kümesi üzerinde ileri geri hareket edebilmek olduğu için, TYPE_SCROLL_SENSITIVE
değerini kullandım. Ayrıca bu değer, yapılan güncellemelerin veya
değişikliklerin ResultSet üzerinde hareket ettiğimizde görünmesinide
sağlamaktaydı. CONCUR_UPDATABLE değeri ise, update
işlemlerinin gerçekleştirilebileceğini belirtmekteydi. Bu değeri tam olarak
anlamış değilim aslında. Sanıyorum ilerleyen zamanlarda kendisini
gösterecektir.
Aslında Statement bileşenini parametresizde
oluşturabilirdim. Bu durumda, kayıt kümesi varsayılan olarak ileri yönlü okumaya
izin veren bir yapıda olacaktı. Dolayısıyla, geriye doğru yapılacak navigasyon
hareketlerine izin vermeyecekti. Bu varsayılan değerde, TYPE_FORWARD_ONLY olarak
belirtilmekteydi. ResultSet' in davranışı belirleyecek başka alan değerleride
vardı. Şu an için bana gerekli olan navigasyona ve insert, update, delete gibi
temel tablo işlemlerine izin veren bir ResultSet idi.
ResultSet' in elde edilmesi ise, tanımlanan
Statement nesnesinin, executeQuery metodu sayesinde gerçekleştirilmekteydi. Bu
metoda parametre olarak çalışmasını istediğim Sql cümleciğini vermiştim. Artık
elimde Sql sunucusundaki Personel tablosunda yer alan verlileri uygulama
ortamına taşıyan bir veri kümesi vardı. Şimdi uygulamayı test etme zamanı
gelmişti. Hemen derleme işlemini gerçekleştirdikten sonra uygulamayı çalıştırdım
ve Baglan başlıklı butona bastım. Herhangibir exception çıkmadığından, veri
kümesini elde ettiğimi düşünüyordum. Şimdi ise asıl önemli olan ilk satırın
verilerini, Frame' deki swing bileşenlerine nasıl dolduracağımdı. ResultSet
nesnem üzerinde ileri geri hareket edebilmekteydim. İlk satıra gitmek için
first, son satıra gitmek için last, önceki satır için previous ve sonraki satır
için ise next metodları vardı. Önce, veri kümesindeki alan değerlerini
bileşenlere yazacak ortak bir metod yazdım.
void Goster()
{
try
{
this.lbID.setText(rsPersonel.getString("PersonelID"));
this.tfAd.setText(rsPersonel.getString("PersonelAd"));
this.tfSoyad.setText(rsPersonel.getString("PersonelSoyad"));
this.tfUcret.setText(rsPersonel.getString("SaatUcreti"));
this.tfSure.setText(rsPersonel.getString("CalismaSuresi"));
}
catch(Exception ex)
{
}
} |
Buradaki kod satırlarında, ilgili bileşenlere
setText metodu ile alan değerlerini yüklüyordum. Bunun içinde, ResultSet
sınıfının getString metodu ile alan adını kullandım. Tabi almak istediğim değer
integer olsaydı getInt metodunu veya tarih olsaydı getDate metodunu vb.' nı
kullanabilirdim. Bu işlemlerin ardından, Doldur başlıklı butona ait kod
satırlarını ve diğer navigasyon butonlarına ait olay kodlarını aşağıdaki gibi
düzenledim.
public java.sql.ResultSet rsPersonel;
public java.sql.Connection conPersonel;
void btnDoldur_actionPerformed(ActionEvent e)
{
try
{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
java.sql.Connection conPersonel =
java.sql.DriverManager.getConnection(
"jdbc:odbc:sqlBaglanti");
java.sql.Statement sqlPersonel =
conPersonel.createStatement(java.sql.ResultSet.TYPE_SCROLL_SENSITIVE,java.sql.ResultSet.CONCUR_UPDATABLE);
rsPersonel =
sqlPersonel.executeQuery("SELECT * FROM Personel");
rsPersonel.first();
Goster();
}
catch(Exception ex)
{
System.out.println(ex.getMessage());
}
}
void btnIlk_actionPerformed(ActionEvent e) {
try
{
rsPersonel.first();
Goster();
}
catch(Exception ex)
{
}
}
void btnOnceki_actionPerformed(ActionEvent e) {
try
{
rsPersonel.previous();
Goster();
}
catch(Exception ex)
{
}
}
void btnSonraki_actionPerformed(ActionEvent e) {
try
{
rsPersonel.next();
Goster();
}
catch(Exception ex)
{
}
}
void btnSon_actionPerformed(ActionEvent e) {
try
{
rsPersonel.last();
Goster();
}
catch(Exception ex)
{
}
}void
this_windowClosing(WindowEvent e) {
if(rsPersonel!=null)
{
try
{
rsPersonel.close();
conPersonel.close();
}
catch(Exception hata)
{
}
}
} |
Uygulamamı çalıştırdığımda herşey istediğim
gibiydi. Satırlar arasında gezebiliyordum.

Şimd ise istediğim, verileri güncelleyebilmek ve
yeni satır veriler girebilmekti. Kaynaklarımı araştırdığımda, ResultSet
sınıfının bu işlemler için kullandığı metodlar olduğunu farkettim. Bu konuları
kısa bir sür inceledikten sonra Frame'e güncelleme ve ekleme işlemleri için iki
button kontrolü ekledim ve aşağıdaki olay kodlarını oluşturdum.
void
btngGuncelle_actionPerformed(ActionEvent e) {
try
{
rsPersonel.updateString("PersonelSoyad",tfSoyad.getText().toString());
rsPersonel.updateString("PersonelAd",tfAd.getText().toString());
java.math.BigDecimal ucret=new
java.math.BigDecimal(tfUcret.getText().toString());
rsPersonel.updateBigDecimal("SaatUcreti",ucret);
java.math.BigDecimal sure=new
java.math.BigDecimal(tfSure.getText().toString());
rsPersonel.updateBigDecimal("CalismaSuresi",sure);
rsPersonel.updateRow();
}
catch(Exception ex)
{
System.out.println(ex.getMessage());
}
}
void btnEkle_actionPerformed(ActionEvent e) {
try
{
rsPersonel.moveToInsertRow();
rsPersonel.updateString("PersonelSoyad",tfSoyad.getText().toString());
rsPersonel.updateString("PersonelAd",tfAd.getText().toString());
java.math.BigDecimal ucret=new
java.math.BigDecimal(tfUcret.getText().toString());
rsPersonel.updateBigDecimal("SaatUcreti",ucret);
java.math.BigDecimal sure=new
java.math.BigDecimal(tfSure.getText().toString());
rsPersonel.updateBigDecimal("CalismaSuresi",sure);
rsPersonel.insertRow();
}
catch(Exception ex)
{
System.out.println(ex.getMessage().toString());
}
} |
ResultSet bileşenin işaret ettiği veri kümesine
yeni bir satır eklemek için, önce moveToInsertRow metodu ile yeni bir satır
açılıyor ve cursor bu satıra konumlandırılıyordu. Daha sonra ise, updateString
ve updateBigDecimal metodları ile, ilk parametre olarak verilen alanlara, ikinci
parametredeki değerler yani textField bileşenlerinin içerikleri atanıyordu. Son
olarak ise, insertRow metodu çağırılarak oluşturulan yeni satır ResultSet' e
ekleniyordu. Güncelleme işlemindede teknik aynıydı. Sadece insertRow yerine
updateRow metodu kullanılmaktaydı. Elbette buradaki güncelleme işlemleri için,
yine Statement nesnesi kullanılabilirdi. Şöyleki; bu nesne ile sql cümlecikleri
çalıştırılabildiğine göre insert ve update sql cümleciklerini çalışıtırarakta
ekleme ve güncelleme işlemlerini yaptırabilirdim.
JDBC ile ilgili konular gerçekten saymak ile
bitmiyor ve bitecek gibide değil. Bu konu ile ilgili olarak yeni bir 24 kahve
molası yapsam az geleceğine inanıyorum. Ancak araştırmaya devam etmekte
elbetteki büyük fayda var. Yorucu bir hafta sonrası JDBC ile çok fazla şey
yapamasamda en azından biraz kulak dolgunluğu yakalamış durumdayım. Ancak tabiki
yeterli değil. Bakalım gelecek kahve molalarında Java okyanusunun hangi derin
sularında, ne yükseklikteki çalkantılı dalgalarla boğuşuyor olacağım.
Burak Selim ŞENYURT
selim@bsenyurt.com