2016-03-30 42 views
0

birçok ilişkilere örtük birçok JPA içinde temsil etmek istiyorum Aşağıda belirtilen eski veri modelini düşünün:Modelleme JPA

  • Diller id ve name var.
  • Dil Açıklamaları, bir id ve language_id ve ek olarak description'dan oluşan bir bileşik birincil anahtara sahiptir, böylece her çeviri için her dil için bir giriş vardır.
  • Makaleler, yukarıda bahsedilen languagedescription_id ile tanımlanan (uluslararasılaşmış) tanımlamaya sahiptir.

Şimdi benim ilk yaklaşım teknik olarak haberler (ideal dil açıklamalarına dilin bir eşleme olmanın çevirilerin bir listesi var, çünkü a) doğru değil

@Entity 
public class Language { 

    @Id 
    @Column(length = 3) 
    private String id; 

    private String languageDescription; 

    // ... 
} 

@Embeddable 
public class LanguageDescriptionId implements Serializable { 

    @Column(length = 9) 
    private String id; 

    @Column(length = 3) 
    private String languageId; 

    // ... 
} 

@Entity 
public class LanguageDescription { 

    @EmbeddedId 
    private LanguageDescriptionId languageDescriptionId; 

    @ManyToOne 
    @MapsId(value = "languageId") 
    private Language language; 

    @Column(length = 60) 
    private String description; 

    // ... 
} 

@Entity 
public class Article { 

    @Id 
    private String id; 

    @ManyToOne 
    private LanguageDescription languageDescription; 
} 

gibi varlıkları modeli oldu Belirli bir dil için bir çeviriyi kolayca almak için) ve b) birden çok yedek girdiyi önlemek için yalnızca languagedescription_id numaralı makaleye atıfta bulunmakla birlikte, ORM (EclipseLink) öğesinin languagedescription birincil anahtar sütunlarını article tablosuna eklediğinden veritabanı durumuna neden olur.

@Entity 
public class Article { 

    @Id 
    private String id; 

    @ManyToMany 
    private List<LanguageDescription> languageDescriptions; 
} 

ile Article varlık değiştirirken benim ORM ben elle doldurmak zorunda kalacak ve hangi gereksiz bilgilerle (eski) veri modelini uzanacak bir eşleştirme tablosu oluşturur. Şu anda benim yaklaşım JPA desteği atlayarak ve @EntityListener çevirileri getirilirken

@Entity 
public class Article { 

    @Id 
    private String id; 

    @Column(length = 9) 
    private String languageDescriptionId; 
} 

gibi Article varlık modellemektir.

Şimdi, bu durum bir şekilde JPA'da otomatik olarak yönetilebilir mi, yoksa JPA'da hiç desteklenmeyen bir eşleme tablosu olmaksızın pek çok ilişkiye bu kadar "örtük" mü?

Örnek

public class Main { 

    public static void main(String[] args) { 
     final Language english = createLanguage("language_1", "English"); 
     final Language german = createLanguage("language_2", "German"); 

     createArticle1(english, german); 
     createArticle2(english, german); 
    } 

    private static Language createLanguage(String id, String languageDescription) { 
     final Language language = new Language(); 
     language.setId(id); 
     language.setLanguageDescription(languageDescription); 

     return language; 
    } 

    private static void createArticle1(Language english, Language german) { 
     final String languageDescriptionId = "languagedescription_1"; 

     final LanguageDescription languageDescription1 = new LanguageDescription(); 
     final LanguageDescriptionId languageDescriptionId1 = new LanguageDescriptionId(); 
     languageDescriptionId1.setId(languageDescriptionId); 
     languageDescriptionId1.setLanguageId(english.getId()); 
     languageDescription1.setLanguageDescriptionId(languageDescriptionId1); 
     languageDescription1.setLanguage(english); 
     languageDescription1.setDescription("Engine"); 

     final LanguageDescription languageDescription2 = new LanguageDescription(); 
     final LanguageDescriptionId languageDescriptionId2 = new LanguageDescriptionId(); 
     languageDescriptionId2.setId(languageDescriptionId); 
     languageDescriptionId2.setLanguageId(german.getId()); 
     languageDescription2.setLanguageDescriptionId(languageDescriptionId2); 
     languageDescription2.setLanguage(german); 
     languageDescription2.setDescription("Motor"); 

     final Article article1 = new Article(); 
     article1.setId("a_1"); 
     article1.setLanguageDescriptionId(languageDescriptionId); 
    } 

    private static void createArticle2(Language english, Language german) { 
     final String languageDescriptionId = "languagedescription_2"; 

     final LanguageDescription languageDescription3 = new LanguageDescription(); 
     final LanguageDescriptionId languageDescriptionId3 = new LanguageDescriptionId(); 
     languageDescriptionId3.setId(languageDescriptionId); 
     languageDescriptionId3.setLanguageId(english.getId()); 
     languageDescription3.setLanguageDescriptionId(languageDescriptionId3); 
     languageDescription3.setLanguage(english); 
     languageDescription3.setDescription("Turn Signal"); 

     final LanguageDescription languageDescription4 = new LanguageDescription(); 
     final LanguageDescriptionId languageDescriptionId4 = new LanguageDescriptionId(); 
     languageDescriptionId4.setId(languageDescriptionId); 
     languageDescriptionId4.setLanguageId(german.getId()); 
     languageDescription4.setLanguageDescriptionId(languageDescriptionId4); 
     languageDescription4.setLanguage(german); 
     languageDescription4.setDescription("Blinker"); 

     final Article article2 = new Article(); 
     article2.setId("a_2"); 
     article2.setLanguageDescriptionId(languageDescriptionId); 
    } 
} 
+0

Veritabanı modeliniz açık değildir. Dil Dil Tanımlaması için neden birleşik PK var, DilDescriptionId.id benzersiz değil mi? Makaleye yabancı bir anahtar mı, yoksa değeri nasıl belirlenir/belirlenir? ManyToMany eşlemeleri bir birleşim tablosu kullanır, ancak bunun yerine bir joinToolsn ile bir OneToMany belirtebilirsiniz. JPA, PK'leri birincil anahtara gitmeye zorlar ve önbellekleme ve sayısız performans nedenleriyle tavsiye edilirken EclipseLink, FK'yi eşlemelerde pk olmayan alanlara da desteklemektedir. – Chris

+0

"Neden LanguageDescription dili için bir bileşik PK var, LanguageDescriptionId.id benzersiz değil mi?" - Hayır, bir LanguageDescription ID, LanguageDescription ID ve dil kimliği birleşimi ile benzersiz hale getirilmiş her dil için bir çeviri içeren bir çeviriler listesiyle eşleşir. "Makaleye yabancı bir anahtar mı, yoksa değeri nasıl belirlenir/belirlenir?" - makaleler, eski veri modelinde LanguageDescription ID'ye sahiptir ve bir dizi DilDescription'ı işaret eder. Ayrıca, @OneToMany, çeviriler makaleler üzerinde yeniden kullanılabilir ve ek bir katılım tablosu oluşturmak istemiyorum. – Smutje

+0

Tablolarınızı açıklamak ya da göstermek zorundasınız, çünkü bunun bir çeviriyle nasıl bir ilişkisi olduğu net değil. DilDescriptionId alanlarını nasıl ayarlayacağınız ve listelerinizi nasıl değiştireceğiniz de net değildir. İkinci seçeneğiniz, makalede languageDescriptionId için bir String kullanmanın en iyi seçeneğiniz olduğunu ve daha sonra ilgili LanguageDescription'ın bu eşleşen languageDd ile toplanmasını sorgulamak, daha sonra karmaşık ve yapay ManyToMany kurallarını modelinize eklemek yerine en iyi seçimdir. Modelinizdeki ilişkilerin önbelleğe alınması her zaman en iyi çözüm değildir. Sorgulama yapabilmeniz için en iyi çözüm – Chris

cevap

0

aşağıdaki gibi bir şey mümkündür: LanguageDescription Kompozit PK olduğu gibi EclipseLink ve diğer sağlayıcılar doğrulama atmak böylece

@Entity 
public class Article { 

    @Id 
    private String id; 

    @Column(length = 9) 
    private String languageDescriptionId; 

    @OneToMany 
    @JoinColumn(name="ID", referencedColumnName="LANGUAGEDESCRIPTIONID", insertable=false, updatable=false) 
    private List<LanguageDescription> languageDescriptions; 
} 

Şimdi yukarıdaki OneToMany, değil JPA uyumludur İstisnalar, sadece neye benzeyeceğinin bir örneğidir. Geçiş yapmak ya da başka bir birleştirme sütunu eklemek için, yalnızca doğrulamayı geçmek ve sonra bir tanımlayıcı özelleştiricisinde eşlemeyi değiştirmek veya eklemeniz gerekir. Bu, buradaki yanıtlarda bir şekilde tarif edilmiş ve gösterilmiştir: jpa, eclips-link 2.5.1: OneToMany not working on columns not primary key

+0

Teşekkürler - doğru çeviri aslında '@ Transient' olduğu ve '@ EntityListener' üzerinden yüklenerek hedef çeviriyi belirlemek için '' Dil '' kullanıcı oturumlarını kullanarak cevabınızı kabul edeceğim. – Smutje