Bu hafta oldukça mutluyum. Nitekim, JBuilder
programını kullanan arkadaşım tatilden döndü. İlk fırsatta ona uğramayı ve
JBuilder ile yeni bir şeyler yapmayı düşünüyordum. Ofisten içeri girdiğimde,
arkadaşım beni görünce hafif bir tebessüm ile şöyle dedi; "Bir kahve molası
veriyoruz ha!". Başımı hafifçe öne eğmem, ofise geliş amacımı açıkça ortaya
koymuştu. Kısa bir muhabbetin ve güzel yaz tatili serüvenlerinin ardından,
arkadaşımın bilgisayarı ve JBuilder ile baş başa kalmıştım. Uzun süredir merak
ettiğim bir uygulamayı geliştirmek istiyordum. Bir veritabanı uygulaması.
Açıkçası JBuilder ile bu tarz bir uygulamanın nasıl yazılacağını merak
ediyordum.
Bundan bir kaç sene öncesine kadar bir Delphi
programcısı olmam, Borland firmasının yazılım geliştirme uygulamalarına olan
aşinalığımı arttıran bir etken olmuştu. Delphi programlama dilinin bana verdiği
en önemli kazanç, gelişmiş bileşen paketleri sayesinde, patronun benden istediği
uygulamaları zamanından çok önce geliştirebilmem olmuştur. JBuilder uygulama
geliştirme ortamı içinde aynı şeyin söz konusu olduğundan emindim. Nitekim bu
bir yandan iyi, diğer yandanda kötü bir olgudur. Delphi gibi geliştirme
ortamları, bir programcının analitik düşünce sistemini ve kod yazma
alışkanlıklarını tembelleştirir. Zaten bu bu .net platformuna geçip C# dilini
öğrenmemin nedenlerinden sadece birisiydi. Ancak, yinede zaman zaman uygulama
geliştirirken Visual Studio.Net ortamını kullanmakta ve avantajlarından
yararlanmaktayım. Buna rağmen, Visual Studio.Net, programcıyı daha çok kod
yazmaya ve algoritma geliştirmeye davet ederek daha bilgili olmamızı
gerektiriyor diyebilirim. Sonuç olarak yinede, JBuilder gibi bir geliştirme
ortamını kullanarak neler yapılabileceğinide görmekte fayda var. Özellikede
yoğun projelerde çalışanlar için, uygulama geliştirme süresinin kısaltılması son
derece önemli bir faktör.
Ben bu düşüncelerim ile boğuşurken bir anda
kendimi, JBuilder ile veritabanı uygulaması geliştirirken bulmuştum. Öncelikle,
işin nasıl yapıldığını kavramam gerekiyordu. Bu amaçla JBuilder' ın tutorial'
larında biraz inceleme yaptım. Daha sonra ise uygulamayı geliştirmeye başladım.
Herşeyden önce bana, kullanabileceğim bir veritabanı gerekliydi. Bunu
gerçekleştirebilmek için, yerel sql sunucusu üzerinde yer alan Northwind
veritabani altında personel isimli bir tablo oluşturdum.

Personel tablosunda, personelin saat ücreti ve
çalıştığı süre ile isim ve soyisim bilgileri yer almakta. Aslında bu tabloda
toplam ücretin yer aldığı bir sütunda oluşturulabilirdi. Ancak ben bu sütunu,
JBuilder uygulaması içinde bir calculated field olarak oluşturmayı planlıyorum.
Personel tablosunu bu şekilde oluşturduktan sonra, bir kaç satırda veri girdim.
Artık JBuilder uygulamasını geliştirmeye başlayabilirdim. İlk yapmam gereken,
bir Java Projesi açmaktı. Projemi sihirbaz adımlarını izleyerekten kısa bir
sürede oluşturdum. Önce birinci adım,

Sonra ikinci adım,

Son olarakta üçüncü adım,

Buraya kadar yapılan işlemler, JBuilder ile
oluşturduğum Applet uygulamasındaki adımlar ile aynıydı. Sırada, uygulama tipini
seçmem ve oluşturmam vardı. Bu sefer, windows üzerinde çalışacak bir uygulama
geliştirmek istiyordum. Bu nedenle, File->New menüsünden açılan Object Gallery
iletişim penceresindeki General kısmından Application şablonunu seçtim.

Elbette seçtiğim Application şablonu için belli
adımları işlemem gerekiyordu. Karşımdaki sihirbaz adımlarınıda hızlı bir şekilde
gerçekleştirerek yoluma devam ettim. Önce ilk adım,

Arından ikinci adım,

Ardından üçüncü ve son adım.

Application için gerekli Frame' de oluşturulduktan
sonra, ilk yaptığım iş, Frame' in Layout özelliğini XYLayout olarak ayarlamak
oldu. Nedense bu Layout' lardan çok çektim Java' da. Ancak JBuilder benim için
esnek bir çözüm sağlamıştı. XYLayout ile, bileşenlerimi frame üzerine bağımsız
bir şekilde yerleştirebilmekteydim. Bu adımlara rağmen halen daha veritabanı
uygulamasını yazmaya başlayamamıştım. İlk olarak neye ihtiyacım olduğunu
düşündüm. Net ortamında uygulama geliştirirken, veritabanına doğru bir bağlantı
hattını tesis etmeme yardımcı olacak Connection nesnelerini kullanıyordum. İlk
önce bileşenler paletinde, bu tarz bir öğe aradım. DataExpress sekmesindeki
Database bileşeni bu arayışımın cevabı oldu. Bu bileşen ile, bağlanmak istediğim
veritabanına bir hat çekebileceğimi düşünüyordum.

Hemen Database bileşenini Frame üzerine çizdim ve
özelliklerine baktım. Connection özelliğine tıkladığımda, bağlantı ayarlarını
yapabileceğim, Connection iletişim penceresi ile karşılaştım. Bu iletişim
penceresinde yer alan Driver kısmında, sistemdeki veritabanlarına erişimimi
sağlayacak çeşitli java veri sürücülerinin olduğunu farkettim. Ancak bunlardan
bazıları kırmızı font ile yazılmışlardı. Sonradan, kırmızı font ile yazılmış
veri sürücülerinin sistemde yüklü olmadığını anladım. Elimde, kullanabileceğim
JdbcOdbcDriver sürücüsü vardı. Bu sürücü ile sistemdeki ODBC kaynaklarına
bağlanabilirdim.

Bu sürücüyü seçtikten sonra ise, URL kısmına
girdim. Ancak tabiki, sql sunucusunda yer alan Northwind veritabanı için bir
System DSN' i tanımlamadığımdan, Northwind veritabanım bu listede görünmüyordu.
Hemen Administrative Tool kısmından, ODBC ayarlarına girdim ve sqlBaglanti
isimli bir System DSN' ini oluşturdum. Tekrar, JBuilder ortamına döndüğümde, URL
sekmesinde, henüz oluşturduğum System DSN' inin eklendiğini farkettim.

Bu işlemlerin ardından Test Connection butonua
basarak bağlantının başarılı bir şekilde sağlanıp sağlanmadığına baktım. Artık
veritabanıma üstelikte yerel makinedeki sql sunucusuna bağlanabileceğim bir
Database bileşenim olmuştu. Şimdi ise, bu veritabanındaki Personel isimli
tabloda yer alan verileri bir şekilde uygulama ortamına çekmem gerekiyordu.
Bunun için bir sql query' si kullanabilirdim. Ancak bu sql query' sini
çalıştıracak ve bir veri kümesi olarak ortama aktaracak bir bileşene ihtiyacım
vardı. Kaynaklarımdan yaptığım incelemelerden sonra, DataExpress sekmesinde yer
alan QueryDataSet bileşeninin aradığım kontrol olduğunu öğrendim.

Bu bileşenin en önemli özelliği, query
özelliğiydi. Query özelliğine girdiğimde, Query iletişim penceresi ile
karşılaştım. Bu iletişim penceresinde, kullanacağım bağlantıyı sağlayan database
bileşenini seçtim. Böylece query bileşenime, hangi veritabanı üzerindeki
tablolar ile çalışacağını belirtmiş oluyordum.

Query bileşeninin, kullanacağı sorguyu, SQL
Builder sekmesinden seçebileceğim gibi, direkt olarak SQL statement kısmınada
yazabilirdim. SQL Builder kısmı, sql sorgusunu kolayca ve detaylı bir şekilde
hazırlayabileceğim bir seçenek sunuyordu. Burada filtreleme, gruplama, sıralama
ve sorgunun testi gibi işlemleri kolayaca gerçekleştirebileceğim adımlar yer
almaktaydı.

Sonuç olarak burada oluşturduğum sql cümleciği
aşağıdaki gibi olmuştu.

Test Query butonua tıklayarak sorguyu test ettim.
Sorgunun başarılı bir şekilde çalıştırılabildiğini gösteren Success ibaresinden
sonra işlemlerime devam etmeye hazırdım. Buradaki query seçenekleri arasında
önemli olanlarından bir tanesi da, "Execute query immediately when opened"
ibaresiydi. Bu seçeneğin işaretli olması ile, uygulama çalışmaya başladığında
query' nin otomatik olarak yürütülmesi ve queryDataSet bileşeni ile bağlı olan
kontrollerin dolması sağlanıyordu.
Bu adımlardan sonra, sırada uygulamaya ait Frame
bileşenlerinin oluşturulması vardı. Bu amaçla dbSwing sekmesi altındaki
bileşenleri kullanabilirdim. İlk olarak, Delphi zamanlarından aklımda kalan bir
bileşeni Frame' e yerleştirmeye karar verdim. JdbNavToolBar. Tabi delphi' de bu
bileşenin adı farklıydı ama şekil itibariyle neredeyse aynıydı. Bu bileşen,
çekilen veri kümesi üzerinde gezinmemi, yeni satırlar eklememi, satırları
düzenlememi, güncellememi vb... işlemleri kolayca yapmamı sağlayacaktı.

Bileşenimi Frame üzerine ekledikten sonra yapmam
gereken tek şey, dataSet özelliğine, queryDataSet1 bileşenini atamak oldu.
Böylece, navigator bileşenimi, ilgili veri kümesi ile ilişkilendirmiştim. Bu
adımıda tamamladıktan sonra, Frame üzerine Personel tablosundaki satır
verilerini gösterecek dbTextField ve dbLabel bileşenlerini ekledim. Bu db
bileşenlerininde query özelliklerine, queryDataSet1 bileşenini atadım. Diğer
yandan, bu bileşenlerin hangi sütunlardaki verileri göstereceğini belirlemek
amacıyla dataColumn özelliklerinede ilgili Column isimlerini atadım. Örneğin,
PersonelAd sütunu için;

Sonuç olarak Frame tasarımım aşağıdaki gibi
olmuştu.

Artık uygulamamı çalıştırabilirdim. Bunun için
sabırsızlanıyordum. Hemen işe koyuldum ve uygulamayı Run ettim. Uygulama
çalışıyordu, satırlar arasında gezinebiliyordum. Eş zamanlı olarakta, bileşenler
içindeki veriler değişiyordu.

Derken hemen yeni bir kayıt eklemek istedim. Bunun
için tek yapmam gereken navigator bileşenindeki + işaretine basmaktı. Bunu
nerden mi biliyordum. Delphi' deki Navigator bileşeninden tabiki. Ancak, karşıma
beklenmedik bir hata mesajı geldi. Sorun Personel tablosundaki PersonelID
sütunundaydı. Bu sütunu, Primary Key olarak belirlemiştim ve otomatik artan bir
değere göre güncellenmesini ayarlamıştım. Yani, değerini sql sunucusunun kendisi
otomatik olarak belirliyor ve benzersiz olmak şartıyla arttırıyordu.

Hemen hata mesajında belirtilen değişiklikleri
yaptım. queryDataSet1 bileşeninin, MetaDataUpdate özelliğindeki RowID
seçeneğinin işaretini kaldırdım.

Daha sonra ise, PersonelID sütununun
özelliklerinden, rowID özelliğinin değerini true olarak değiştirdim. Bu
işlemlerden sonra, uygulamamı tekrar çalıştırdığımda artık kayıt ekleyebiliyor,
güncelleyebiliyor ve silebiliyordum. Ancak yapmış olduğum bu değişiklikler,
sadece queryDataSet bileşenin temsil ettiği veri kümesi üzerinde
gerçekleşiyordu. Yani bağlantısız katman üzerinde. Asıl veri tablosuna bu
değişikliklerin yansıtılabilmesi için, Navigator bileşenindeki Save Changes
ipucu textine sahip butonun tıklanması gerekiyordu.
Şimdi ise sıra calculated field' ın
oluşturulmasına gelmişti. Amacım, Saat ücretleri ile çalışma sürelerinin
çarpımını veren bir calculated field oluşturmaktı. Bunu gerçekleştirebilmek için
öncelikle yeni bir alana ihtiyacım vardı. Bu alan Personel tablosu üzerinde
değil, queryDataSet bileşeni üzerinde oluşturulacaktı. Başka bir deyişle çalışma
zamanında oluşturulacak ve offline olarak çalışacaktı. Bu alanı ekleyebilmek
için, queryDataSet1 bileşenine çift tıklayarak açılan penceredeki + butonunu
kullandım.

Yeni alanın columnName özelliği ile ismini,
caption özelliği ile başlığını, name özelliği ilede bileşen adını belirttikten
sonra, dataType özelliğinide BIGDECIMAL olarak belirledim. Nitekim Sql
sunucusunda decimal olarak belirtilen veri tipi, java ortamında BIGDECIMAL
olarak eşleştirilmekteydi. Bunlara ek olarak, calcType özelliğinide calculated
olarak değiştirmem gerektiğini uygulamayı bu haliyle derlediğim zaman aldığım
hata mesajlarından anladım. Bu özelliğide düzenledikten sonra artık tek yapmam
gereken, queryDataSet1 bileşeninin calcFields olayını kodlamak olacaktı. Bu olay
metodu, calculated field' lar için gerekli hesaplamaların yapıldığı yerde
devreye girmekteydi. Buradaki kodları aşağıdaki gibi oluşturdum.
void queryDataSet1_calcFields(ReadRow
changedRow, DataRow calcRow, boolean isPosted)
{
java.math.BigDecimal saat=chancedRow.getBigDecimal("SaatUcreti");
java.math.BigDecimal
sure=chancedRow.getBigDecimal("CalismaSuresi");
java.math.BigDecimal toplamUcret = saat.multiply(sure);
calcRow.setBigDecimal("ToplamUcret",toplamUcret);
}
|
Bu kodlarda ilk dikkati çeken nokta, chancedRow
parametresi ile güncel satır bilgisine erişilmesiydi. İlk olarak, SaatUcreti ve
CalismaSuresi alanlarının değerlerini, ReadRow sınıfından bir örnek olan
chancedRow parametresinin getBigDecimal metodu ile, BigDecimal türünden bir
değişkene aktarıyorduk. Sonra ise ilginç bir kod satırı çalıştırılıyordu.
Nitekim normal şartlar altında iki değişkeni çarpmak istediğimde bildiğim çarpma
operatörünü kullanırdım. Ancak burada aşağıdaki kod satırını yazdığımda,
| java.math.BibDecimal toplamUcret =
saat * sure; |
* operatörünün, BigDecimal tipine uygulanamıyacağı
söyleyen bir derleme zamanı hatası alıyordum. Bunun üzerine kaynaklarımı kısa
bir süre araştırdığımda, BigDecimal tipindeki değişkenlerden birisine multiply
metodunu kullanarak, çarpma işlemini gerçekleştirebileceğimi keşfetmiştim.
Calculated field alanının değerine hesaplanan değeri aktarmak için, bu alanı
temsil edecek DataRow sınıfının bir örneği olan calcRow parametresinin
setBigDecimal metodunu kullandım. Bu işlemlerin ardından, hesaplanan alana ait
bilgilerin ekranda gösterilmesini sağlamak amacıyla Frame üzerine, bir
JdbLabel bileşeni ekledim. Uygulamamı çalıştırdığımda, ToplamUcret alanının her
bir satır için hesaplandığını ve yapılan güncellemelerdende etkilendiğini
farkettim. Bu basit uygulama sorunsuz çalışıyordu. Üstelikte 4 satır kod yazmama
rağmen.

Elbetteki bir veritabanı uygulamasında
yapılabilecekler sadece bunlar ile sınırlı değildi. Örneğin, buradaki
bileşenleri kullanmadan, JDBC sınıfları yardımıyla bu işlemler nasıl
gerçekleştirilebilirdi? Yada bir stored procedure nasıl çalıştırılabilirdi ?
Hatta arama, filtreleme gibi işlemler için kodları nasıl düzenlemek gerekiyordu?
Bu gibi konuları incelemeye fırsat kalmadan saatin epeyce ilerlediğini ve
arkadaşımın ofisi kapamak üzere olduğunu farkettim. Uzun süre boyunca beni
izlemiş ve bilgisayar başında nasıl kendimden geçtiğimi seyretmişti. Sonuçta
konsantremi bozmak istememişti ama saatin gece yarsını geçtiğinide birisinin
bana söylemesi gerekiyordu. "Artık bir sonraki kahve molasına kadar
dinlenmelisin" dediğinde, içtiğim kahve bardaklarının masa başında uzunca bir
kuyruk oluşturduğunu farketmiştim. İlerleyen haftalar, JDBC ile ilgili yeni
araştırmaların habercisiydi.
Burak Selim ŞENYURT
selim@bsenyurt.com