2009-10-05 15 views
7

Bir Oracle uygulamasında Hibernate ile bir Java uygulamasından erişmek istediğim eski tablolarım var. Sorun şu: tabloların iyi birincil anahtarları yok. Örneğin, bir tablo bu şekilde görünecektir:İyi bir PK olmadan Oracle eski tablosu: Nasıl Hazırda Bekletilir?

create table employee (
    first_name varchar(64) not null, 
    last_name  varchar(64) not null, 
    hired_at  date, 
    department varchar(64) 
); 
create unique index emp_uidx on employee (firstname, lastname, hired_at); 

orijinal tasarımcı veritabanı şirket dışından John Smiths birbirinden ayırt etmek gerek asla düşünerek bir durum alanı olarak hired_at sütun kullanmaya karar verdi, ama bu Aynı ada sahip çalışanlar, hired_at tarihleriyle tanımlanabilir. Açıkçası, bu kısmen nemli ve değiştirilebilir bir birincil anahtar oluşturur. Veri tabanı bunu birincil anahtar olarak kabul etmeyeceğinden, bunun yerine benzersiz bir dizinle gitti. Ben bunun için bir hazırda eşleme yazmaya çalışırsanız

Şimdi, ben böyle bir şey ile gelebilir:

<hibernate-mapping> 
    <class name="com.snakeoil.personnel" table="employee"> 
    <composite-id class="com.snakeoil.personnel.EmpId" name="id"> 
     <key-property name="firstName" column="first_name" type="string"/> 
     <key-property name="lastName" column="last_name" type="string"/> 
    </composite-id> 
    <property name="hiredAt" column="hired_at" type="date"/> 
    <property name="department" type="string"> 
    </class> 
</hibernate-mapping> 

Bu okuma verileri için çalışır, ama sadece farklı yeni girişler oluştururken onların HiredAt date, org.hibernate.NonUniqueObjectExceptions içine koşuyorum. de

<id column="ROWID" name="id" type="string"> 
    <generator class="native"/> 
</id> 

Bu okuma verileri için çalışıyor: Alternatif olarak, i Oracle'ın ROWID özelliğini düşünebilirsiniz. Fakat açıkçası, yeni nesnelere devam edemezsiniz, çünkü Hibernate şimdi bir org.hibernate.exception.SQLGrammarException atar: varlıkları depolamaya çalışırken sıradaki sekans değerini alamadı.

Bunun açık yolu, vekil anahtarlarıdır. Ancak bu, veritabanı şemasının değiştirilmesini gerektirecek, bu da bizi bu "eski" şeylere geri getirecek.

Neye bakıyorum? Hibernate'in Oracle'ın ROWID'iyle, belki de farklı bir jeneratörle işbirliği yapmasının bir yolu var mı? Ya da ilk fikir çalışmasını yapmanın bir yolu var mıdır, belki de varlıkların çoğunu tahliye eden ve yeniden yükleyen akıllı DAO'larla ve karmaşıklığı uygulamadan gizlemek için mi? Ya da hazırda beklemede bir alternatif aramalıyım, belki de Ibatis?

cevap

7

Birincil bir anahtar olarak ROWID kullanmak istemezsiniz, çünkü bir satırın ömrü boyunca kararlı olması garanti edilmez.

Bir sentetik anahtar eklemek en iyi seçimdir. Sütunu bir sıra değeriyle doldurmak için bir tetikleyici kullanın.

Sen eski yönü üzerinde biraz belirsiz, nedenle etkileri nelerdir emin olmak zordur. Bir sütun eklemek, hedef sütunları açıkça listelemeyen ek ifadelerini keser. onlar bir değişken haline seçmek %ROWTYPE anahtar sözcüğüyle bildirilmiş olmadıkça Ayrıca (herhangi bir SELECT * sorguları bozabilir Ama bunun yerine varolan kolonların yeni birincil anahtar kullanılan bu yüzden başka herhangi bir uygulama değiştirmek zorunda olmaz -. Eğer gerçekten istemedikçe.

+0

Evet, bu iyi bir fikir gibi görünüyor Diğer tüm seçenekler cruftastic DAO sihirli gerektirecek gibi görünüyor – wallenborn

+1

Oracle ROWID olan '' kararlı (alıntı) Tek sorun zaman Örneğin, o zaman yardımcı programları değişebilir.Sonra bir satırı silerseniz, Oracle daha sonra eklenmiş olan yeni bir satıra tekrar satır atayabilir. – xmedeko

+0

@xmedeko - bu paragrafın ilk cümlesini bilerek bırakmış olabilirsiniz. Bir tablonun birincil anahtarı olarak ROWID. "Http://docs.oracle.com/cd/B19306_01/server.102/b14200/pseudocolumns008.htm – APC

5

Bir destek dizisiyle bir vekil anahtar eklerim. Eski semantiklerin hiçbirini değiştirmez ve Hazırda Bekletme tatmin olur.

Yalnızca meraklı - eğer indeks adın soyadı ve soyadı ve tarihine sahipse, neden kompozit anahtarınız kiralanma tarihini hariç tutuyor? İndeksteki tüm alanları kompozit anahtarda da görmeyi beklerdim.

+0

i (Smith, John 2009-10-01) ve (Smith, John null) ve (Smith, Jack null), varsa hazırda, Yani. null değerleri döndürür, bunu yaparsan bir i umuyordum, null alanına bir sıradan özelliği yaptı neden lastName = 'Smith'' üç girdileri, bir (Smith, John 2009-10-01) ve iki boş işaretçiler döneceğini Çalışan gelen queryon '. budur "DAO'larda düzeltmek için._If Silmek İthalat ve İhracat içeren bir satır yeniden takın. ".. – wallenborn

İlgili konular