Yazarlar Sözlük Makaleler Yardım Masası Gözlük Forum İstatistik

Java - JDBC


Özet
JDBC (Java Database Connectivity) yi daha performanslı nasıl kullanabiliriz ?

Yazar Hakkında
Şehir :
İstanbul

Üyelik :
15 Haziran 2005 14:33

Son Giriş :
08 Haziran 2006 11:28
» Mesaj gönder
» alperen_hakki hakkında
» Sözlükte alperen_hakki
JDBC (Java Database Connectivity) Java nın veritabanına ulaşmak için kullandığı standard API ye verilen addır. JDBC nin etkin kullanımı genel performansı önemli ölçüde etkileyen parametrelerdendir. Aşağıda JDBC hakkında dikkat edilmesi gereken birkaç noktaya değinmeye çalıştım :

1) Veritabanına olan bağlantıyı sağlamak için DataSource kullanmalıdır.
JDBC 2.0+ DataSource u desteklemektedir.DataSource objelerinin konfirigasyonu J2EE container ı üzerinde yapılır, veritabanı bağlantısını sağlar ve yönetir, pool mekanizması ve transaction desteği sağlar.
Eskiden kullanılan yönteme örnek verelim :
Class.forName(“oracle.jdbc.driver.OracleDriver”);
DriverManager.getConnection(“jdbc:oracle:thin:@host:port:sid”,username,pwd);
Bu DataSource ile birlikte şu şekilde yapılmalıdır :
InitialContext ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup(“java:comp/env/jdbc/OracleDS”)
Connection conn = ds.getConnection();
Not : OracleDS, burada veritabanının adıdır. Uygulama, “ejb-jar.xml” dediğimiz xml dosyasına InitialContext in lookup metodu ile bakar. Karşılığı olan “connection pool” u bulur ve bu pool üzerinden veritabanı bağlantısını kurar.

2) Veritabanı bağlantılarını pool mekanizması üzerinden yapılmalıdır.
Veritabanına klasik fiziksel bağlantı kurmak ve bunun üzerinden işlem yapmak maliyetlidir. Connection pool ile kurulan bağlantılar tekrar tekrar kullanılabilir. Ama diğer türlü, bir bağlantı kurulur ve işlem bitince sonlanır. Pool mantığında ise aynı bağlantı tekrar tekrar kullanılabilir. Pool tanımları application server üzerinde yapılır.

3) Mümkün olduğunca PrepairedStatement kullanılmalıdır.
Veritabanı bağlantısını sağladıktan sonra artık veritabanında işlemler yapmaya başlayabiliriz. Bunu “statement” dediğimiz objelerle sağlarız. 3 çeşit statement objesi vardır :
- statement
- preparedStatement
- CallableStatement

“Statement” ve “preparedStatement” ile SELECT, UPDATE gibi temel SQL leri calıştırırken “CallableStatement” ile veritabanında bir fonksiyon ya da procedure cağırmak için kullanırız.
Statement ile prepairedStatement arasındaki fark, ikincisinde bir kere derleme olur ve belirtilen parametreleri girmek suretiyle SQL’in tekrar tekrar kullanılması sağlanır. Bu da performasnı arttırır. Birincisinde ise her çağrılma durumunda derleme işlemleri her seferinde tekrarlanır. Örnekler :
Statement stmt = con.createStatement();

ResultSet rs = stmt.executeQuery(”SELECT a, b, c FROM Table”);

PreparedStatement pstmt = con.prepareStatement(
“INSERT INTO EMPLOYEES  (NAME, PHONE) VALUES (?, ?)”);
pstmt.setString(1, theName);
pstmt.setString(2, thePhone);
pstmt.executeUpdate();

4) Kullandıgımız herhangibir kaynağı işimiz bitince kapatmalıyız.
Kullandıgımız kaynak connection olsun, ResultSet olsun, statement lardan biri olsun işimiz bitince kapatılmalıdır. Bunu try-catch bloğundan sonraki finally bloğu ile sağlayabiliriz.
ResultSet rset = null;
PreparedStatement pstmt = null;
Connection conn = null;

try {
…
}
catch(Exception e) {
  …
}
finally{
  if(rset!=null)
    rset.close();

  if(pstmt!=null)
    pstmt.close();

  if(conn!=null)
    conn.close();
}

5) AutoCommit özelliğini control altında tutmalıdır.
JDBC ile sağlanan veritabanı bağlantıları varsayılan olarak “autocommit”tir. Yani yapılan her DML işlemi sizin isteğiniz dışında commitlenir. Bu hem istenmeyen durumlara yol açar hem de çok sık commit etmenin oluşturacğı olası performans kayıplarına yol açabilir:
pstmt.setLong(1,2345);
pstmt.setString(2,”Sam”);
pstmt.execute(); à COMMIT
pstmt.setLong(1,2346);
pstmt.setString(2,”Steve”);
pstmt.execute();à COMMIT
pstmt.setLong(1,2347);
pstmt.setString(3,”Scott”);
pstmt.execute();à COMMIT
Bunu engellemek oldukça kolaydır.Yapılması gereken tek şey DML işlemlerimiz başlamadan autocommit özelliğini kapamak ve işlem bitince kendimizin commit etmesidir.Yani :
connection.setAutoCommit(false);
pstmt.setLong(1,2345);
pstmt.setString(2,”Sam”);
pstmt.execute();
pstmt.setLong(1,2346);
pstmt.setString(2,”Steve”);
pstmt.execute();
pstmt.setLong(1,2347);
pstmt.setString(3,”Scott”);
pstmt.execute();
connection.commit();

6) Tekrarlanan Batch işlemler için statement batching kullanılmaldır.
Diyelimki devamlı sekilde bir insert yapıyoruz, bunu da preparedStatement ile yaptık. Her seferinde derleme olmuyor aynı SQL tekrar tekrar kullanılabiliyor. Bu uygulamamızı daha da performanslı yapmanın yolu var. Diyelim 10 tane insert yapılacak. Bunu 10 kez veritabanına gidip yapmak mıdır yoksa 10unu birden tek seferde gidip yapmak mıdır? Elbette 2.si. JDBC bu konuda da esneklik sağlıyor. Aşağıdaki gibi bir değişiklikle bu tip işlemlerimizin batch seklinde yapılmasını sağlayabiliriz :
PreparedStatement pstmt = null;
pstmt = conn.prepareStatement(”insert into emp(empno,ename)
                                 values(?,?)”);
pstmt.setLong(1,101);
pstmt.setString(2,Ahmet);
pstmt.addBatch();
pstmt.setLong(1,102);
pstmt.setString(2,Alperen);
pstmt.addBatch();
  …
int resultValues[] = pstmt.executeBatch(); // examine resultValues[] to see status of
  // each batch operation

7) ResultSet i gereğinden fazla şişirmemelidir.
Örnegin 30 kolonlu bir tabloda bir işlemimiz için sadece 4 kolona ihtiyacımız var iken “select *” kullanmak gereksiz kaynak tüketmeye ve performans kaybına yol açacaktır.
“select *” haliyle calistirildığı anda network üzerinde giden gelen veri büyüklüğü ile 4 kolonun veri büyüklüğünü karşılaştırmak konuyu daha iyi anlamamızı sağlayacaktır.

Bunların yanında aşağıdaki noktalara da dikkat etmekte fayda var :

i) Kolon ve satir bazında cekilen data miktarını azaltmak ya da arttırmak performansı etkiler.Bunu kontrol etmek için Statement objesinin setMaxRows, setMaxFieldSize, and SetFetchSize metodlarından faydalanılır.

ii) ResultSet ile değer alırken getObject metodu yerine alacağımız verinin tipinde bir get metodu kullanmak daha performanslı olacaktır. (getInt(), getString() gibi)

iii) Yine ResutSet ile kolon bilgilerini alırken kolonların adını kullanmak yerine select teki sırasına göre kullanmalıdır. (rs.getString(1) gibi)

hakki.oktay@gmail.com
http://hakki.oracleturk.org




Yazarımıza ait diğer makaleler

1. Java ile mail gönderme örneği (javax.mail.*)
Java ile bir mail server üzerinden mail gönderme hakkında örnek
01 Haziran 2006 08:56

2. Oracle'da Data Concurrency ve Consistency Kavramları
Aynı anda aynı tablo hatta aynı satırlar üzerinde işlem yapan çok kullanıcılı sistemler artık kaçınılmaz.Hal böyle olunca bilgilerin tutarlılığının sağlanması istenmeyen sonuçları almamak açısından çok önemlidir. Peki Oracle bu anlamda nasıl çalışıyor ve hangi mekanizmaları nasıl kullanıyor?
24 Mayıs 2006 16:09

Yorumlar

1.  Makale için teşekkürler. Sadece Java'cıların değil diğer dillerde yazılım geliştirenlerinde faydalanacağı bilgiler var burada.

Merak ettiğim bir şeyi sorayım : Java'da .NET'in DataSet'ine benzer bir yapı var mı?
fizikci
23 Mayıs 2006 14:51
2.  Açıkçası .NET hakkında bir bilgim yok.Ama DataSet, Java da zannedersem ResultSet e tekabül ediyor.Bir database fonksiyonu, prosedürü ya da sadece bir select i çalıştırdıgınız da geriye bir sonuç kümesi dönüyorsa (select ya da cursor)bunu ResulSet ile alırsınız.Tek bir deger dönüyorsa (integer, String, obje ya da obje dizisi) getXXX metodları ile sonuçları alırsınız.Kısaca DB den donen sonuclar ResultSet ile alınır.Bu ifadeler cok basit anlatımlar oldu ama kabaca bu sekilde ifade etmek mümkün.Umarm sorunuza cevap olmuştur.Basit bir orneği su linkte bulabilirsiniz :
http://javaalmanac.com/egs/java.sql/GetRsData.html ,
İlerleyen günlerde (vaktim olduğunda) bu konu ile ilgili bir yazıda yazarım.İyi çalışmalar....
alperen_hakki
24 Mayıs 2006 14:11
3.  Java'nın ResultSet'i tam olarak .NET'in DataReader sınıfına karşılık geliyor. Onda da getXXX metodları var. Veritabanına hızlı, forward only erişim sağlıyor.

DataSet ise bağlantısız çalışabiliyor. Veritabanını tam olarak modelleyebiliyor. Veritabanı kavramlarının DataSet sınıf yapısındaki karşılıkları şöyle:

Database   -> DataSet
Table      -> DataTable
Row        -> DataRow
Field      -> DataColumn
Forign Key -> DataRelation
...
...

Bu yaklaşımın bir benzeri Java'da olmasa bile third party yazılımlar bunu sağlıyor olabilir. Gerekli mi değil mi, o ayrı mevzu tabi. :)
fizikci
24 Mayıs 2006 19:21
Bu konuda bildiklerinizi bizlerle paylaşabilirsiniz
Tabi bunun için yazarsanız giriş yapmalı, yazar değilseniz yazar olmalısınız.
© 2005, Bilişim Kulübü. (1109 ms)
Ne yapabilirsin: SubtitleClick ile İngilizceni Geliştir, Çınar Framework ile kod yaz, Eglencelik.org'ta biraz eğlen