2012-10-04 13 views
17

To musi być dość naiwna, ale mam wątpliwości, kiedy używać @Entity i @Embeddable.@embeddable vs @entity na mapowanie kolekcji

Powiedz, że mam klasę User i Notification.

@Entity 
public class User{ 
    //other properties 
    @onetomany 
    private List<Notification> notifications; 
} 

@Entity 
public class Notification{ 
    //properties 
} 

Rozumiem, że nie będzie stoły do ​​klasy User i Notification i trzeciej tabeli dla mapowania. Co, jeśli zrobię to w ten sposób?

@Entity 
public class User { 
    //other properties 
    @ElementCollection 
    private List<Notification> notifications; 
} 

@Embeddable 
public class Notification{ 
    //properties 
} 

wiem, że to nie będzie utworzyć tabelę dla Notification. Ale nadal mogę przechowywać moje obiekty powiadomień. Przeszedłem przez documentation, ale kilka wątpliwości:

  1. Czy to jest oparte na tym, czy chcę zobaczyć klasę B jako oddzielny stolik?
  2. Czy występuje różnica wydajności b/w powodująca utworzenie tabeli i obiektu do osadzenia?
  3. Czego nie mogę zrobić z obiektem embedable, który można zrobić za pomocą tabeli innej niż bezpośrednio w tabeli?

UWAGI

Dla każdego, kto czyta to pytanie, to question też może pomóc.

Odpowiedz

8
  1. Czy opiera się na tym, czy chcę zobaczyć klasę B jako oddzielną tabelę?

Tak, podczas korzystania @Embedded, osadzić że @Embeddable podmiot @Entity klasy, co sprawia, że ​​dodanie kolumny do wbudowanego podmiotu w tej samej tabeli @Entity klasie.

  1. Czy istnieje różnica wydajności b/w tworząc tabelę i obiekt do osadzenia?

Podczas korzystania z @Embedded do tworzenia tabeli wymagane jest jedno zapytanie, również do wstawiania i wybierania wiersza. Ale jeśli go nie używasz, potrzeba wielu zapytań, dlatego użycie @Embedded daje więcej wydajności, możemy powiedzieć.

  1. Czego nie mogę zrobić z obiektem embedable, który mogę zrobić z tabelą inną niż zapytanie bezpośrednio do tabeli?

Usunięcie odpowiedniego elementu wbudowanego może być możliwe, ale mogą być do tego naruszenia ograniczenia integralności.

+0

Przypuszczam, że mogę używać Embeddable z ElementCollection. Nie muszę używać @Embedded rt? – shazinltc

+0

Nie dostałem twojego trzeciego punktu. – shazinltc

+0

Trzeci punkt: rozważ Osobę zawiera Adres (osadzony), jeśli istnieje osobna tabela dla obu, Możesz bezpośrednio usunąć powiązany adres, ale jeśli tabela Osoby ma F.K. do adresowania, może to spowodować naruszenie ograniczenia integralności. – deepakraut

0

W języku WZP istnieje kilka sposobów tworzenia złożonych pól kluczowych. Zobacz metodę wykorzystującą @Embeddable annotation.
Zacznijmy od klasy Entity.

@Entity 
@Table 
public class TraceRecord { 
    @Id 
    private TraceRecordPk id; 

    @Version 
    @Transient 
    private int version; 

    @Column(columnDefinition = "char") 
    private String durationOfCall; 

    @Column(columnDefinition = "char") 
    private String digitsDialed; 

    @Column(columnDefinition = "char") 
    private String prefixCalled; 

    @Column(columnDefinition = "char") 
    private String areaCodeCalled; 

    @Column(columnDefinition = "char") 
    private String numberCalled; 
} 

Jest to całkiem prosta klasa jednostek z polem @Id i @Version oraz kilkoma definicjami @Column. Nie wdając się w szczegóły, zauważysz, że pole @Version również zawiera adnotację @Transient. Zrobiłem to po prostu dlatego, że mój stół również nie ma kolumny do śledzenia wersji, ale moja baza danych jest kronikowana, więc nie jestem zbytnio zaniepokojony wersjonowaniem. Zauważysz również, że pola @Column mają wartość "char" ustawioną w atrybucie columnDefinition. Dzieje się tak dlatego, że pola w mojej tabeli są zdefiniowane jako char, a nie varchar. Gdyby byli varchar, nie musiałbym tego robić, ponieważ String domyślnie mapuje do pola varchar.

Pole @Id jest tym, co mnie interesuje właśnie teraz. Nie jest to standardowy typ Java, ale klasa, którą sam zdefiniowałem. Oto ta klasa.

@Embeddable 
public class TraceRecordPk implements Serializable { 

    private static final long serialVersionUID = 1L; 

    @Temporal(TemporalType.DATE) 
    @Column 
    private Date dateOfCall; 

    @Column(columnDefinition="char") 
    private String timeOfCall; 

    @Column(columnDefinition="char") 
    private String callingParty; 

    /** 
    * Constructor that takes values for all 3 members. 
    * 
    * @param dateOfCall Date the call was made 
    * @param timeOfCall Time the call was made 
    * @param callingParty Extension from which the call originated 
    */ 
    public TraceRecordPk(Date dateOfCall, String timeOfCall, String callingParty) { 
     this.dateOfCall = dateOfCall; 
     this.timeOfCall = timeOfCall; 
     this.callingParty = callingParty; 
    } 
} 

Aby ta klasa zdolne do pola @Id na klasy Entity, musi być opatrzone @Embeddable jak wspominałem wcześniej. Trzy pola wybrane dla mojego klucza złożonego są po prostu normalnymi definicjami @Column. Zamiast tworzyć obiekty pobierające/ustawiające dla każdego pola, po prostu zaimplementowałem konstruktor, który przyjmuje wartości dla wszystkich 3 pól, czyniąc każdą instancję niezmienną. Podczas adnotowania klasy za pomocą @Embeddable, ta klasa będzie musiała zaimplementować Serializable. Dlatego dodałem domyślny identyfikator serialVersionUID, aby się do niego dostosować.

Teraz, gdy masz klasę utworzoną i opatrzoną adnotacją z @Embeddable, możesz teraz używać jej jako typu dla pola @Id w klasie Entity. Proste rzeczy eh.

+0

Dzięki, ale przeczytałem to [artykuł] (http://jpgmr.wordpress.com/2011/03/27/using-the-jpa-embeddable-annotation-to-create-your-own-composite-keys /). To nie odpowiada na moje pytanie. Moje pytanie i tak nie jest związane z kluczami kompozytowymi. – shazinltc

Powiązane problemy