ArÅŸiv

‘Java Teknolojileri’ kategorisi için arÅŸiv

Hibernate @Version – OptimisticLockException

Çarşamba, 29 Ara 2010 Yorum yapılmamış

Hibernate, @Version ile işaretlenen kolon sayesinde bir oturumda açılan varlık nesnesinin, diğer bir oturumda değiştirilmesine izin vermeyerek OptimisticLockException fırlatır. Bu istisna yakalanarak ilgili işlemler yapılabilir. Değişiklik yapılmak istenen varlık nesnesinin başka bir oturumda değiştirildiği belirtilerek kullanıcı yönlendirilebilir örneğin.

@Version ile işaretlenmiş kolon Long, Integer veya TimeStamp tipinde olabilir. Hibernate bu nesne (veritabanında karşılığı olan satır) üzerinde gerçekleştirilen persist() ve sonraki her bir merge() işlemi ile beraber versiyon kolonunun değerini bir arttırır.

@Entity
public class Flight implements Serializable {

@Version
@Column(name=”OPTLOCK”)
private Integer version {

}

}

Şöyle ifade edebiliriz sanırım; Nesnenin veritabanından okudunduÄŸu zamanki versiyonuna ilkVersiyon, yapılan deÄŸiÅŸiklikler veritabanına yansıtılmadan hemen evvelki versiyona sonVersiyon dersek Hibernate API’nin deÄŸiÅŸiklikleri veritabanına yansıtan metodu olan EntityManager.flush() ilkVersiyon.equals(sonVersiyon) kontrolu yapar. Ä°ki versiyon deÄŸeri eÅŸitse deÄŸiÅŸiklikleri veritabanına yansıtır, farklıysa -ki bu ilgili satırın bir baÅŸka oturumda deÄŸiÅŸtirildiÄŸi anlamına gelir- OptimisticLockException fırlatır. Bu durumdaki nesne “stale object” tanımına girer.

BahsettiÄŸim hata;

javax.ejb.EJBException: javax.persistence.OptimisticLockException: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect)

gibi bir hatadır.

Burada dikkat edilmesi gereken EntityManager sınıfının executeUpdate() metodunun bu versiyon alanının değerini arttırmadığı. Bu yüzden ilgili varlık sınıfları için böylesi bir işlem yapılmadığına dikkat etmek gerekiyor ki neden OptimisticLockException almıyoruz diye debelenmeyelim.

Ve java gurusu abilerimizden Hakan Uygun der ki, bu yöntem ilgili nesneyi barındıran her veritabanı işlemi için (yukarıdaki gibi bir versiyon numarası eşitliği gerçekleştirmek adına) bir sorgu daha çekmek demek. Dolayısıyla bu kolonu öyle ilgili ilgisiz her varlık sınıfına eklememek gerekir. Ayrıca bir çözüm değil, sadece böylesi eş zamanlı düzenleme işlemlerinde alınabilecek hataları engellemek adına uygulanabilecek bir yöntemdir.

Konuyla ilgili daha detaylı bilgi için şuraya bakılabilir.

FacebooktwitterlinkedinmailFacebooktwitterlinkedinmail

Eclipse Debug Pratikleri

Cumartesi, 18 Ara 2010 Yorum yapılmamış

Eclipse’in bir kaç debug görünümü özelliÄŸinden bahsedeyim.

Drop to frame drop_to_frame

Bu sayede herhangi bir debug işlemi sırasında en baştaki breakpoint noktasında dönebiliyorsunuz. Tabi bu arada çalışan kodun meydan getirdiği değişiklikleri geri alma gibi bir özellik söz konusu değil.

Watchpoint

Herhangi bir genel değişkenin (global variable) olduğu satıra çift tıklayarak eklenebilir. Böylece değişken her değişikliğe uğradığında debug görünümüne dönüş yapılabilir.

Add java exception breakpoint addJavaException

Bu özellik ile de kodun çalışması sırasında meydana gelebilecek herhangi bir istisna yakalanıp, bu istisna durumunun incelenebilmesini saÄŸlanıyor. Burada eklenecek istisna Java’da bütün istisnaların türediÄŸi sınıf olan “Exception” seçilirse mesela bütün istisna durumlarında Eclipse debug görünümüne dönebiliyor, veya özel bir “Exception” (OptimisticLockException, SQLGrammarException vs.) türü belirterek onu yakalayabiliyoruz. Bu daha çok yakalanmayan veya yakalama gereÄŸi duyulmayan “NullPointerException”, “IndexOutOfBoundsException” gibi istisna durumlarında faydalı olur gibi geliyor.

Skip all breakpointsskipAllBreakPoints

Pratikte çok işe yarayan, çoğu Eclipse kullanıcısının biliyor olması gereken bir özellik. Bu sayede tek tek breakpoint leri devre dışı bırakmak yerine, bütün breakpoint leri devre dışı bırakarak kodun normal çalışmasını takip edebiliyoruz.

Enable when – Hit count

Son olarak, pratikte çok ihtiyaç olmazmış gibi gözükse de, bir breakpoint in ne zaman aktif olacağını o breakpoint in özellikler kısmından “Enable when” kısmına yazacağımız kod ile belirleyebiliyoruz. Şöyle bir durumda iÅŸe yaramışlığına ÅŸahidim; Diyelim ki 200 elamana sahip bir listede for döngüsü ile iÅŸlem yapıyoruz. Hatanın da 50 ila 60. elamanlar arasında bir yerlerde olduÄŸunu biliyoruz.

for(int i = 0; i < list.size(); i++){
...
}

Böyle bir durumda “Enable When” kısmına i >= 50; yazarak ilgili breakpoint in 50.adımla beraber aktif olmasını saÄŸlamış, biraz zaman biraz sabır kazanmış oluyoruz.

Yine ilgili breakpoint in özellikler kısmından kaç kereden sonra pasif olacağını da “Hit count” ile belirleyebiliyoruz.

FacebooktwitterlinkedinmailFacebooktwitterlinkedinmail

Java – Object – Clone() Metodu

PerÅŸembe, 25 Kas 2010 5 yorum

Java’da bütün sınıfların türediÄŸi Object sınıfının bir metodu olan clone() ile bir nesnenin kopyasını almak mümkün. Fakat pratikte bir takım sıkıntılar ile karşılaşılabiliyor. Bunun sebebi clone() metodunun primitive olmayan tipler için, nesnenin kopyasını almak yerine bu nesnenin referansını kopyalıyor olması. Buna “Shadow Copy” deniyor. Bu gibi durumlarda clone() metodunu ezip, nasıl bir kopyalama yapacağını belirlememiz gerekiyor. Sınıf tipi (Class Type) alanları da “gerçekten” kopyaladığımız bu tür kopyalamaya da “Deep Copy” deniyor.

Tabi kopyasını almak istediÄŸimiz sınıfın “Cloneable” arayüzünü gerçeklemesi gerekiyor. Bu ÅŸekilde sınıf tanımında “implements Cloneable” ÅŸeklinde bir belirtim yapmazsak “CloneNotSupportedException” fırlatılıyor. Daha sonra bir “Deep Copy” gerekiyor ise, ki gerçekte muhtemelen gerekiyordur, clone() metodunu eziyoruz (override). Bu gibi “Deep Copy” yapmak istediÄŸimiz durumlarda yapabileceÄŸimiz iki ÅŸey var. Birincisi gerçek kopyasını almak istediÄŸimiz sınıfın sınıf tipindeki alanlarini da “Cloneable” yapıp bahsi geçen clone() metodunda bu clone() metotlarını çağırıp, bu sınıf tipindeki alanlara atamak.

@Override
       public Object clone() {
		Employee e = null;
		try {
			e = (Employee) super.clone();
                        Department d = e.getDepartment().clone();
                        e.setDepartment(d);
		} catch (CloneNotSupportedException cnsex) {
			//TODO:catch this 
		}
		return e;
	}

İkincisi ise clone() metodunda gerçek nesneler oluşturarak bunları kopyalanmak istenen nesnenin sınıf tipindeki alanlara atamak.

@Override
	public Object clone() {
		Employee e = null;
		try {
			e = (Employee) super.clone();
                        e.setSalary(BigDecimal.ZERO);
		} catch (CloneNotSupportedException cnsex) {
			//TODO:catch this 
		}
		return e;
	}

Önemli bir diğer ilke de kopyalama sonucu oluşan kopya nesne ile kopyalanan asıl nesne için kopyaNesne != asılNesne ifadesinin, kopya işlemi sonrası ilk aşamada kopyaNesne.equals(asılNesne) ifadesinin ve kopyaNesne.getClass() != asılNesne.getClass() ifadesinin her zaman doğru değer döndürmesi gerektiğidir. Son olarak kopyalanmak istenen sınıfın List veya Set gibi Collection sınıfından türeyen alanları mevcutsa ve bunları da gerçekten kopyalamak istiyorsak, bu listelerin her bir elemanını tek tek kopyalamamız gerektiğini unutmamak gerekiyor.

Bu kadar yazdık ettik ama yine de Java gurusu abilerimiz nesne kopyalama işlemleri için clone() metoduna çok güvenmeyip ve bağlı kalmayıp bunun yerine istediğimiz şekilde kopyalamayı gerçekleştiren yapılandırıcı metotlar yazmamızı salık veriyorlar bize.

Güncelleme : Örnek koda ve kod yorumlarına şuradan bakılabilir. Umarım daha açıklayıcı olmuştur.

Ayrıca konu ile ilgili faydalı olduğunu düşündüğüm şuraya da bakmakta fayda var.

FacebooktwitterlinkedinmailFacebooktwitterlinkedinmail
Kategoriler:Java Etiketler:, , ,

Java Collections.sort() – Collator

Pazar, 29 AÄŸu 2010 5 yorum

Java’nın Collections sınıfının faydalı bir bir metotundan bahsedeyim. Listeleri istediÄŸimiz gibi sıralamamız saÄŸlayan sort() metodu.

Bu gibi sıralama işlemlerinde en çok yaşanan sıkıntılardan bir tanesi String türünde verileri kıyaslarken ortaya çıkan Türkçe karakter sorunu. Şırnak, Çanakkale, Ordu illerini sıraladığımızda Çanakkale, Ordu, Şırnak sırasını beklerken mesela, Ordu-Çanakkale-Şırnak şeklinde bir sıranın ortaya çıkması gibi. Bu gibi durumlarda yerel karakter duyarlılığıyla kıyas yapabilen ve parametre olarak bir Locale alabilen Collator sınıfı yardımcı olacaktır.

BahsettiÄŸimiz sort() metodunun iki versiyonu bulunuyor;

Collections.sort(List<T> list)

ArrayList, LinkedList, Vector gibi List interface’ini implement eden bir sınıfı parametre olarak alıyor. Metodu bu ÅŸekli ile kullanabilmemiz için listenin barındırdığı elemanların tipi olan sınıf, Comparable sınıfını implement etmek durumunda.

Sadece kitap adını tutan, Kitap adında basit bir sınıfımız olduÄŸunu düşünelim. Bu sınıf implement ettiÄŸi Comparable interface’ nin compareTo() metodunu implement etmek durumunda.

 
public class Kitap implements Comparable<Kitap> {

	private String ad;

	public String getAd() {
		return ad;
	}

	public void setAd(String ad) {
		this.ad = ad;
	}

	@Override
	public int compareTo(Kitap kitap) {
	Collator collator = Collator.getInstance(Locale.getDefault());
        //veya Collator trCollator = Collator.getInstance(new Locale("tr", "TR"));
	return collator.compare(this.getAd(), o.getAd());
	}
}

Artık kitaplarımızı şu şekilde sıralayabiliriz;

...
List<Kitap> kitapListesi = getKitaplar();
Collections.sort(kitapListesi);
...
Collections.sort(List<T> list, Comparator<T> comparator)

; metodun bu versiyonu biri List diğeri de Comparator interface lerini implement eden sınıfları parametre olarak alıyor. Kitaplarımızı sıralama işlemi için bu kez Comparator interface ini implement eden Comparator bir sınıf tanımlıyoruz. Yine kitap adına göre sıraladığımızı varsayarsak compareTo() metodu şu şekilde olacaktır;

public class KitapComparator implements Comparator<Kitap>{

@Override
public int compare(Kitap kitap1, Kitap kitap2) {
Collator collator = Collator.getInstance(Locale.getDefault());
//veya Collator trCollator = Collator.getInstance(new Locale("tr", "TR"));
return collator.compare(kitap1.getAd, kitap2.getAd());
}
}

gibi kitaplarımızı karşılaştıran bir sınıf tanımladıktan sonra

...
List>Kitap> kitapListesi = getKitaplar();
Collections.sort(kitapListesi, new KitapComparator());
...

gibi bir ifade ile de kitapListesi sıralanmış bir hal alıyor.

Benzer şekilde gereklilikler doğrultusunda comparator sınıflar tanımlayıp ihtiyaç halinde kullanılabilir.

FacebooktwitterlinkedinmailFacebooktwitterlinkedinmail

Java – Lambdaj Kütüphanesi

Cumartesi, 21 AÄŸu 2010 1 yorum

Java Collections API sınıflarını kullanırken bolca for döngüleri kurar veya bu tip veriler üzerinden istediğimiz işlemleri gerçekleştirmek için çeşitli kod blokları yazarız. Lambdaj kütüphanesi bu tip kod blokları ile yaptığımız işlemleri çoğu kere tek satırlık kodlarla halletmemizi sağlayan bir arayüz sunuyor bize. Böylece listelere bir veri kaynağıymışcasına hemen her türlü seçim, sıralama, gruplama, dönüştürme, indeksleme ve benzeri işlemleri gerçekleştirebiliyoruz. Hatta zaman zaman for döngüleri ile halledemeyeceğimiz işleri bile karşılayabiliyor.

Elbetteki kod okunurluğunu arttırıp, bakımının kolaylaşmasını sağlarken performansı aşağı çekiyor. Her ne kadar performanstan ciddi kayıplar yaşatabilse de, varlığının bilinmesi kimi zamanlar çözüm getirmekte zorlandığımız problemler için faydalı olacaktır. Bu konuda Lambdaj ile normal tekrarlamalı yöntemler arasındaki performans kıyaslaması yapan şu makaleye göz atılabilir.

Lambdaj‘ ın yetenekleri ile ilgili bazı örnekler vermek gerekirse;

Person tipinde nesneler tutan listemizde her bir Person nesnesinin adını tek satırda bilmem ne olarak setlemek;

List personInFamily = getPersons();
forEach(personInFamily).setLastName("Dalton");

Person tipinde nesneler tutan listemizde yaşı 30’dan büyük olanları ayıklamak;

List = getPersons();
List oldFriends = filter(having(on(Person.class).getAge(), greaterThan(30)), meAndMyFriends);

Person tipinde nesneler tutan listemizde toplam yaşı bulmak;

int totalAge = sum(meAndMyFriends, on(Person.class).getAge());

Person tipinde nesneler tutan listemizi yaşa göre sıralamak;

List sorted = sort(persons, on(Person.class).getAge());

Person tipinde nesneler tutan listemizdeki Person nesnelerinin isimlerini birleÅŸtirmek

String friendNames = joinFrom(myFriends).getFirstName();

Person tipinde nesneler tutan listemizden adı Ali olan kaydi bulmak;

List personList = getPersons();
List personListOfAli = select(personList , having( on(Person.class).getFirstName(), equalTo("Ali")));

Örnek kodlar aynı zamanda projenin web sayfası olan şuradan alınmıştır. Ayrıca şuradaki dökümandan daha ayrıntılı bilgi alabilir.

FacebooktwitterlinkedinmailFacebooktwitterlinkedinmail

Object references an unsaved transient instance

Cuma, 07 May 2010 Yorum yapılmamış

Hibernate API ‘yi kullananlar TransientObjectException:Object references an unsaved transient instance – save the transient instance before flushing hatası iÅŸle karşılaÅŸmışlardır mutlaka. Şöyle bir örnek üzerinden açıklayacak olursak; Araba ve Kullanici adli iki modelimiz olduÄŸunu ve Araba modelinde

@ManyToOne()
@JoinColumn(name = “KULLANICI_ID”)
private Kullanici kullanici;

şeklinde bir Kullanici alanımız olduğunu varsayalım. Aksiyon sınıfında;


araba.setKullanici(kullanici);
entityManager.persist(araba);
entityManager.flush();

ÅŸeklinde bir kod bloÄŸu yukarıdaki hatayı almamıza sebep olacaktır. Kullanici nesnesi sessionda varolmasına raÄŸmen henüz veritabaninda mevcut deÄŸildir, yani “transient object” tanımına girmektedir. Araba tablosunda “foreign key” olarak bulunan KULLANICI_ID alanına yerleÅŸtirilecek bir ID yoktur ortalıklarda. Dolayısıyla iliÅŸki kurulamaz. Hatayı iki ÅŸekilde gidermek mümkün. Birincisi kod bloÄŸunu;


araba.setKullanici(kullanici);
entityManager.persist(araba.getKullanici());
entityManager.flush();

entityManager.persist(araba);
entityManager.flush();

şeklinde düzenleyip önce Kullanici nesnesini veritabanına yazmak, ikincisi de ilişkiyi

@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinColumn(name = “KULLANICI_ID”)
private Kullanici kullanici;

şeklinde tanımlayarak bu Araba veritabanına kaydedilirken ve güncellenirken Kullanici nesnesinin de veritabanina yazilmasini sağlamak. Elbette ki sağlıklı olan annotation da ilişkinin özelliğini bildirerek bu gibi kontrolleri ve performansı API nin kendisine bırakmak.

Benzer bir durum OneToMany() ilişkilerde de sözkonusu. Çözüm yine benzer şekilde.

FacebooktwitterlinkedinmailFacebooktwitterlinkedinmail

PMD ile kod analizi

Cumartesi, 24 Nis 2010 Yorum yapılmamış

Sadece Eclipse deÄŸil aynı zamanda diÄŸer bir çok IDE’ye de (JDeveloper, JBuilder, IntelliJ IDEA vs.) eklenebilen gayet faydalı bir eklentiden söz etmek istedim; PMD. Åžurada da bahsedildiÄŸi üzere PMD neyin kısaltması ola ki sorusunun bir sürü cevabı var, veya aslında yok. (Pretty Much Done, Project Mess Detector, Project Monitoring Directives vs.) Yaptığı iÅŸ Java kodunu tarayıp olası hatalara sebebiyet verecek kod parçalarını iÅŸaret etmekle kalmayıp bunların nasıl daha temiz, daha düzgün, daha okunur hale getirilebileceÄŸi konusunda öneriler getirmesi. Taradığı kural setlerinden birkaçını kabaca yazacak olursak;

* Daha iyi ve/veya daha az kodla ifade edilebilcek kod blokları
* Kullanılmayan değişken, parametre, metotlar
* Boş bırakılmış try/catch/finally/switch ifadeleri
* Fazlaca karmaşık, okunması zor ifadeler, metotlar
* Gereksiz if cümlecikleri, while ile değiştirilebilecek for cümlecikleri
* Kopya kod blokları
* Kopyala/yapıştır kaynaklı oluşabilecek hatalar
* Fazlaca uzun veya kısa isimlendirilmiş değişkenler, metotlar

Elbette bunların dışında Java kodunu değerlendirmeye tabi tuttuğu bir dolu kural seti var. Pratikte daha çok karşımıza çıkabilecek olanlardan bahsettim.

Bir iki örnek vermek gerekirse;

Query sınıfının getResultList() metotundan dönen liste değişkeninin içeriğini if(list.size()>0) gibi kontrol etmek yerine list.isEmpty() ile kontrol etsene,

veya String deÄŸiÅŸkenler için eÅŸitlik kontrolü yaparken (a diye String bir deÄŸiÅŸkenimiz olduÄŸunu varsayarsak) if(a.equals(“Ahmet”)) ÅŸeklinde kontrol etme arkadaÅŸ, if((“Ahmet”).equals(a)) diye kontrol ederek muhtemel null pointer hatalarından da sıyrılsan ya,

veya bir baÅŸka örnek BigDecimal tipinden bir deÄŸiÅŸkene new BigDecimal(“0”) ile deÄŸer atadığımız bir ifade için, arkadaÅŸ ne diye statik olarak zaten elinde var olan BigDecimal.ZERO ‘yu kullanmıyorsun ki diyebiliyor. Bu gibi örnekleri çoÄŸaltmak mümkün.

Eklentinin sahip olduğu kural setlerini Window->Preferences->PMD menüsünden düzenleyebiliyoruz da. Böylece hangi kuralı değerlendirmeye alacağını veya nasıl değerlendireceğini belirleyebiliyoruz. İşte efendim ben değişken isimlerini anlaşılır olması adına uzun yazarım, sen karışma benim işime, o yüzden sen beni ancak 20 karakterden daha uzun olarak isimlendirilmiş değişkenler için uyarıver diyebiliyoruz.

Merak edip denemek isteyenler için Eclipse ‘ e nasıl ekleyebileceÄŸimiz ÅŸurada anlatılmış.

Åžurada da PMD’nin sahip olduÄŸu kural setleri ayrıntılı bir ÅŸekilde izah edilmiÅŸ.

FacebooktwitterlinkedinmailFacebooktwitterlinkedinmail
Kategoriler:Eclipse Etiketler:,