Berkeley DB – Java Edition

Gökhan Atıl’ın kişisel blog’undan bir yazıyı sizinle paylaşma istedim. Berkeley DB ile ilgilenenlerin işine yarayacaktır.

Bu aralar NoSQL veritabanlarını inceliyorum. NoSQL veritabanları daha önceden duymamış olabilirsiniz, aslında uzun zamandır bir çok popüler projede kullanılıyorlar (örneğin facebook, digg, twitter, reddit). Bu veritabanlarının ortak özelliği ilişkisel yapıda olmamaları, SQL desteklememeleri ve genel olarak dağıtık mimari için tasarlanmış olmalarıdır. NoSQL veritabanlarından biri de Berkeley DB. Berkeley DB, adından da çağrışım yapılacağı üzere Berkeley üniversitesinde ortaya çıkmış bir yazılım. Genel amaçlı embedded bir veritabanı olan Berkeley DB, transaction, hotbackup ve replikasyon desteğine sahip ve bir çok projenin alt yapısında kullanılmakta. Üreticisi Sleepcat Software’i 2006′da Oracle tarafından alındı ve şu an Oracle tarafından dağıtılan 3 sürümü var:

Berkeley DB
Berkeley DB Java Edition
Berkeley DB XML

Ben bunlar arasında en kolay kullanabileceğim Berkeley DB Java Edition’ı test etmeye karar verdim. Berkeley DB Java Edition, 100% Java ile yazılmış, çok basit bir şekilde projenize eklenebiliyor ve Direct Persistence Layer (DPL) veya “temel API” ile kullanılabiliyor. Anahtar/Değer şeklinde verilerinizi kaydetmeyi sağlıyor. Yani Berkeley DB’de RDBMS’lerden alışa geldiğimiz tablo, kolon yapısı yok. NoSQL veritabanlarında tablolar yerine genelde “kolleksiyonlar” olur ama Berkeley DB’de bu da yok :)

En basit şekilde özetlersek şu şekilde bilgi kaydetmenizi sağlıyor:

Key | Value
—————————–
1 Gökhan
2 Ahmet

Bu basit yapısına rağmen, high avalibility için replikasyon desteği var, ayrıca hotbackup alınabiliyor. Pek çok NoSQL veritabanında dağıtık yapıda verim alınabilmesi açısından görmezden gelinen ACID ve transaction desteği var (opsiyonel olarak açıp, kapatabiliyorsunuz).

Berkeley DB Java Edition için dökümanlar:

http://www.oracle.com/technetwork/database/berkeleydb/documentation/index-160410.html

Berkeley DB Java Edition’ı ve diğer sürümleri şu adresten indirebilirsiniz:

http://www.oracle.com/technetwork/database/berkeleydb/downloads/index.html

Buradan ilgili dosyayı indirip (je-x.x.x.tar.gz/zip), bir klasöre açtığınızda Berkeley DB’yi kullanmak için gerekli JAR kütüphanesine ve örnek Java kodlarına sahip oluyorsunuz. Bundan sonra yapmanız gereken, favori Java IDEniz aracılığıyla bir Java projesi oluşturup je-x.x.x.jar dosyasını projenize eklemek. Berkeley DB ve diğer NoSQL veritabanları SQL desteklemediğinden, veritabanı üzerinde işlem yapabilmek için size sağlanan API kütüphanesini kullanıyorsunuz, ben bunun nasıl yapıldığını göstermek için Java ile “temel API” kullanan bir kaç örnek oluşturalım.

Berkeley DB, veritabanı dosyalarını bir klasör içinde tutuyor. Veritabanını açmak için öncelikle bu klasörü bir “ortam” (Environment) nesnesi olarak tanıtmamız gerekiyor:

Environment vtOrtami = null;
try { EnvironmentConfig ortamKonfigurasyonu = new EnvironmentConfig();
ortamKonfigurasyonu.setAllowCreate(true);
vtOrtami = new Environment(new File(“/data/sampledb”), ortamKonfigurasyonu);
} catch (DatabaseException dbe) { System.out.println(“Berkeley DB ortam oluşturma hatası!”); }

ortamKonfigurasyonu.setAllowCreate(true) sayesinde daha önce bu klasörde veritabanı tanımlanmadıysa otomatik olarak oluşturulmasını sağlıyoruz. Veritabanı ortamını oluşturduktan sonra, bu ortam içinde veritabanı açacağız:

DatabaseConfig vtKonfigurasyonu = new DatabaseConfig();
vtKonfigurasyonu.setTransactional(false);
vtKonfigurasyonu.setAllowCreate(true);
Database ornekVT = vtOrtami.openDatabase( null, “testDB”, vtKonfigurasyonu);

Fark ettiyseniz vtKonfigurasyonu.setTransactional(false) ile veritabanımızın transaction desteğini kapattım. Bir veritabanının transcation desteği olup olmadığını o veritabanını oluştururken belirliyorsunuz. Transaction desteği olan bir veritabanını transaction desteğini kapatarak açmanız veya tersi durum mümkün değil. Ortam olarak belirlediğimiz dizin boş olduğundan bu işlem sonrası transaction desteği olmayan “testDB” adında bir veritabanına sahip olacağız.

Bu oluşturduğumuz veritabanına kayıt eklemek için DatabaseEntry nesnelerinden faydalanıyoruz:

DatabaseEntry anahtar = new DatabaseEntry();
DatabaseEntry veri = new DatabaseEntry();

IntegerBinding.intToEntry( 1, anahtar);
StringBinding.stringToEntry( “GÖKHAN ATIL”, veri);
ornekVT.put(null, anahtar, veri);

Veritabanına kaydetmek istediğimiz anahtar ve değer (key/value) için DatabaseEntry nesneleri oluşturup Binding nesneleri aracılığı ile istediğimiz değer atamalarını yapıyor ve sonra “put” fonksiyonu ile veritabanına bu değerleri kaydediyoruz.

Berkeley DB, sequence yani sayaç nesnelerini destekliyor. Kayıtları yaparken key olarak sayaçtan aldığımız değerleri kullanabiliriz:

SequenceConfig sayacKonfigurasyonu = new SequenceConfig();
sayacKonfigurasyonu.setAllowCreate(true);
StringBinding.stringToEntry(“ORNEK_SAYAC”, veri);
Sequence sayac = ornekVT.openSequence(null, veri, sayacKonfigurasyonu);

IntegerBinding.intToEntry( (int)sayac.get(null, 1), anahtar);
StringBinding.stringToEntry(“VALUE” + i, veri);
ornekVT.put(null, anahtar, veri);

Şimdi bütün bu yazdıklarımı birleştirip, belirlediğimiz klasör altında testDB adında veritabanı oluşturan ve buna 1 milyon kayıt giren örnek bir kod yazalım:

import com.sleepycat.bind.tuple.*;
import com.sleepycat.je.*;
import java.io.File;

public class DBinsert {

public static void main(String[] args) {

Environment vtOrtami = null;

try {
EnvironmentConfig ortamKonfigurasyonu = new EnvironmentConfig();
ortamKonfigurasyonu.setAllowCreate(true);
vtOrtami = new Environment(new File(“/data/sampledb”), ortamKonfigurasyonu);
} catch (DatabaseException dbe) {
System.out.println(“Berkeley DB ortam oluşturma hatası!”);
}

DatabaseConfig vtKonfigurasyonu = new DatabaseConfig();
vtKonfigurasyonu.setTransactional(false);
vtKonfigurasyonu.setAllowCreate(true);
Database ornekVT = vtOrtami.openDatabase( null, “testDB”, vtKonfigurasyonu);

DatabaseEntry anahtar = new DatabaseEntry();
DatabaseEntry veri = new DatabaseEntry();

SequenceConfig sayacKonfigurasyonu = new SequenceConfig();
sayacKonfigurasyonu.setAllowCreate(true);
StringBinding.stringToEntry(“ORNEK_SAYAC”, veri);
Sequence sayac = ornekVT.openSequence(null, veri, sayacKonfigurasyonu);

for( int i = 0; i < 1000000; i++) {
IntegerBinding.intToEntry( (int)sayac.get(null, 1), anahtar);
StringBinding.stringToEntry(“VALUE” + i, veri);
ornekVT.put(null, anahtar, veri);
}

sayac.close();
ornekVT.close();
vtOrtami.close();
}
}

Veritabanından kayıt çekmek için “get” fonksiyonunu kullanıyoruz. Bu yazdığımı veriler arasında rastgele arama yapalım:

import com.sleepycat.bind.tuple.*;
import com.sleepycat.je.*;
import java.io.File;

public class DBselect {

public static void main(String[] args) {

Environment vtOrtami = null;

try {
EnvironmentConfig ortamKonfigurasyonu = new EnvironmentConfig();
ortamKonfigurasyonu.setAllowCreate(true);
vtOrtami = new Environment(new File(“/data/sampledb”), ortamKonfigurasyonu);
} catch (DatabaseException dbe) {
System.out.println(“Berkeley DB ortam oluşturma hatası!”);
}

DatabaseConfig vtKonfigurasyonu = new DatabaseConfig();
vtKonfigurasyonu.setTransactional(false);
vtKonfigurasyonu.setAllowCreate(true);
Database ornekVT = vtOrtami.openDatabase( null, “testDB”, vtKonfigurasyonu);

DatabaseEntry anahtar = new DatabaseEntry();
DatabaseEntry veri = new DatabaseEntry();

Random generator = new Random();

IntegerBinding.intToEntry( generator.nextInt(1000000) , anahtar);

if (ornekVT.get(null,anahtar, veri, null ) == OperationStatus.SUCCESS) {
System.out.println(IntegerBinding.entryToInt(anahtar) + ” : ”
+ StringBinding.entryToString(veri));
}
ornekVT.close();
vtOrtami.close();
}

}

Verileri update etmek için aynı key’e sahip bir kayıdı “put” ile tekrar kaydetmemiz yeterli oluyor. Bu işlem yeni kayıt eklemek yerine veriyi güncelleyecektir.

Integer guncellenecekKayit = 3852301;

IntegerBinding.intToEntry( guncellenecekKayit , anahtar );
StringBinding.stringToEntry(“GOKHAN”, veri);
ornekVT.put( null, anahtar, veri );

if (ornekVT.get(null, anahtar, veri, null ) == OperationStatus.SUCCESS) {
System.out.println(IntegerBinding.entryToInt(anahtar) + ” : ”
+ StringBinding.entryToString(veri));
} else System.out.println(“Kayıt bulunamadı” );
Date bitisZamani = new Date();

Her hangi bir kaydı silmek için delete fonksiyonunu kullanıyoruz:

Integer silinecekKayit = 3852301;

IntegerBinding.intToEntry( silinecekKayit , anahtar );
ornekVT.delete( null, anahtar );

IntegerBinding.intToEntry( silinecekKayit , anahtar);

if (ornekVT.get( null, anahtar, veri, null ) == OperationStatus.SUCCESS) {
System.out.println(IntegerBinding.entryToInt(anahtar) + ” : ”
+ StringBinding.entryToString(veri));
} else System.out.println(“Kayıt bulunamadı” );

Bu örneklerden sonra aklınıza muhemelen şu soru gelmiştir: Berkeley DB’deki Anahtar/veri (key/value) yapısı düşünüldüğünde, yani veritabanında sadece bir anahtar kolonu ve ona karşılık bir değer kolonu tutabildiğimize göre, diğer veritabanlarında olduğu gibi bir kayıt içerisinde birden fazla kolon nasıl tutulabilir?

Bunu aşmak için oluşturduğunuz kayıt yapılarını (nesnelerinizi), tek bir değişkende toplamanız gerekir. DPL (Data Persistence Layer) bu işi çok kolaylaştırıyor. Temel API ile yolunuza devam etmek istiyorsanız, TupleInput ve TupleOutput nesnelerinden faydalanarak nesnelerinizi veritabanına yazılacak tek değişken haline getirebilirsiniz. Bu işlemin nasıl yapıldığını göstermek için örnek bir uygulama yazalım.

İlk önce, saklayacağımız kayıt yapısını içeren bir nesne oluşturuyoruz (OrnekNesne.java):

import com.sleepycat.bind.tuple.TupleBinding;
import com.sleepycat.bind.tuple.TupleInput;
import com.sleepycat.bind.tuple.TupleOutput;
import com.sleepycat.je.DatabaseEntry;

public class OrnekNesne {

private String isim;
private String email;
private String telefon;

public OrnekNesne(String isim, String email, String telefon) {
super();
this.isim = isim;
this.email = email;
this.telefon = telefon;
}

public OrnekNesne() {
super();
this.isim = “Joen Doe”;
this.email = “N/A”;
this.telefon = “N/A”;
}

public void yazdir() {

System.out.println( “İsim……: ” + isim);
System.out.println( “Email…..: ” + email);
System.out.println( “Telefon…: ” + telefon);

}

public String getIsim() {
return isim;
}

public void setIsim(String isim) {
this.isim = isim;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

public String getTelefon() {
return telefon;
}

public void setTelefon(String telefon) {
this.telefon = telefon;
}

public DatabaseEntry objectToEntry() {

TupleOutput output = new TupleOutput();
DatabaseEntry entry = new DatabaseEntry();

output.writeString(getIsim());
output.writeString(getEmail());
output.writeString(getTelefon());

TupleBinding.outputToEntry( output, entry);

return entry;
}

public void entryToObject( DatabaseEntry entry ) {

TupleInput input = TupleBinding.entryToInput(entry);

setIsim(input.readString());
setEmail(input.readString());
setTelefon(input.readString());

}

}

Sonra bu örnek nesnemizi kullanacak kodları yazıyoruz:

import com.sleepycat.bind.tuple.*;
import com.sleepycat.je.*;
import java.io.File;

public class DBinsertobject {

public static void main(String[] args) {

Environment vtOrtami = null;

try {
EnvironmentConfig ortamKonfigurasyonu = new EnvironmentConfig();
ortamKonfigurasyonu.setAllowCreate(true);
vtOrtami = new Environment(new File(“/data/sampledb”),
ortamKonfigurasyonu);
} catch (DatabaseException dbe) {
System.out.println(“Berkeley DB ortam oluşturma hatası!”);
}

DatabaseConfig vtKonfigurasyonu = new DatabaseConfig();
vtKonfigurasyonu.setTransactional(false);
vtKonfigurasyonu.setAllowCreate(true);
Database ornekVT = vtOrtami.openDatabase(null, “nesneDB”,
vtKonfigurasyonu);

DatabaseEntry anahtar = new DatabaseEntry();
DatabaseEntry veri = new DatabaseEntry();

IntegerBinding.intToEntry(1, anahtar);
OrnekNesne gokhanAtil = new OrnekNesne(“Gökhan Atıl”, “gokhan at gokhanatil.com”, “4444444″);
ornekVT.put(null, anahtar, gokhanAtil.objectToEntry() );

IntegerBinding.intToEntry(2, anahtar);
OrnekNesne aliCengiz = new OrnekNesne(“Ali Cengiz”, “ali at cengiz.com”, “5555555″);
ornekVT.put(null, anahtar, aliCengiz.objectToEntry() );

IntegerBinding.intToEntry(3, anahtar);
OrnekNesne hakanBalta = new OrnekNesne(“Hakan Balta”, “hakan at balta.com”, “6666666″);
ornekVT.put(null, anahtar, hakanBalta.objectToEntry() );

IntegerBinding.intToEntry(1, anahtar);
ornekVT.get(null, anahtar, veri, null );

OrnekNesne yeniMusteri = new OrnekNesne();
yeniMusteri.entryToObject(veri);
yeniMusteri.yazdir();

ornekVT.close();
vtOrtami.close();

}
}

Berkeley DB, hızlı ve sağlam yapısı ile projelerinizde kullanmayı düşünebileceğiniz bir veritabanı. Dual lisans ile geliyor. Eğer açık kaynak kodlu yazılım üretiyosanız, ücretsiz olarak bu veritabanını projenize dahil edebilirsiniz. Veritabanına erişmek için yazdığım nesneler bu işin en uygun nesneler olmayabilir, ben açıkçası Berkeley DB nasıl kullanılıyor sorusuna cevap aradığımdan nesneleri modellerken çok titiz davranmadım. Buna karşın bu dökümanın Berkeley DB ile uğraşmak isteyenlere için faydalı olacağını düşünüyorum.

Kaynak: http://www.gokhanatil.com/2010/09/oracle-berkeley-db-java-edition/

Bu yazı toplam 178 kere görüntülenmiştir.

0saves
Eğer yazıyı beğendiyseniz lütfen yorum bırakın veya diğer yazılardan haberdar olmak için RSS'e üye olun..

İlgili Yazılar:

Yazar Hakkında


Yazar:

Hakkında / İlgi Alanları: Php, Python, Java, Güvenlik, Algoritmalar, Fotoğraf, Kitap, Sinema
Kategori: Java, Veritabanları, September 26th, 2010

Yazarlarımızdan , bu yazı dahil toplam 30 adet yazı yazmış.

Cevap yaz