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:,