Birisi mappedBy'yi JPA ve Hibernate'de açıklayabilir mi?


175

Hazırda bekletme konusunda yeniyim ve bire çok ve çoktan bire ilişkiler kullanmam gerekiyor. Nesnelerimdeki iki yönlü bir ilişkidir, böylece her iki yönden de geçebilirim. mappedBybunun için önerilen yol, ancak anlayamadım. Birisi açıklayabilir mi:

  • onu kullanmanın önerilen yolu nedir?
  • hangi amacı çözüyor?

Örneğim adına, ek açıklama içeren sınıflarım:

  • Airline OWNS çok AirlineFlights
  • Birçok AirlineFlights aittir ONE Airline

Havayolu :

@Entity 
@Table(name="Airline")
public class Airline {
    private Integer idAirline;
    private String name;

    private String code;

    private String aliasName;
    private Set<AirlineFlight> airlineFlights = new HashSet<AirlineFlight>(0);

    public Airline(){}

    public Airline(String name, String code, String aliasName, Set<AirlineFlight> flights) {
        setName(name);
        setCode(code);
        setAliasName(aliasName);
        setAirlineFlights(flights);
    }

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="IDAIRLINE", nullable=false)
    public Integer getIdAirline() {
        return idAirline;
    }

    private void setIdAirline(Integer idAirline) {
        this.idAirline = idAirline;
    }

    @Column(name="NAME", nullable=false)
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = DAOUtil.convertToDBString(name);
    }

    @Column(name="CODE", nullable=false, length=3)
    public String getCode() {
        return code;
    }
    public void setCode(String code) {
        this.code = DAOUtil.convertToDBString(code);
    }

    @Column(name="ALIAS", nullable=true)
    public String getAliasName() {
        return aliasName;
    }
    public void setAliasName(String aliasName) {
        if(aliasName != null)
            this.aliasName = DAOUtil.convertToDBString(aliasName);
    }

    @OneToMany(fetch=FetchType.LAZY, cascade = {CascadeType.ALL})
    @JoinColumn(name="IDAIRLINE")
    public Set<AirlineFlight> getAirlineFlights() {
        return airlineFlights;
    }

    public void setAirlineFlights(Set<AirlineFlight> flights) {
        this.airlineFlights = flights;
    }
}

AirlineFlights:

@Entity
@Table(name="AirlineFlight")
public class AirlineFlight {
    private Integer idAirlineFlight;
    private Airline airline;
    private String flightNumber;

    public AirlineFlight(){}

    public AirlineFlight(Airline airline, String flightNumber) {
        setAirline(airline);
        setFlightNumber(flightNumber);
    }

    @Id
    @GeneratedValue(generator="identity")
    @GenericGenerator(name="identity", strategy="identity")
    @Column(name="IDAIRLINEFLIGHT", nullable=false)
    public Integer getIdAirlineFlight() {
        return idAirlineFlight;
    }
    private void setIdAirlineFlight(Integer idAirlineFlight) {
        this.idAirlineFlight = idAirlineFlight;
    }

    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="IDAIRLINE", nullable=false)
    public Airline getAirline() {
        return airline;
    }
    public void setAirline(Airline airline) {
        this.airline = airline;
    }

    @Column(name="FLIGHTNUMBER", nullable=false)
    public String getFlightNumber() {
        return flightNumber;
    }
    public void setFlightNumber(String flightNumber) {
        this.flightNumber = DAOUtil.convertToDBString(flightNumber);
    }
}

DÜZENLE:

Veritabanı şeması:

AirlineFlights'ın idAirline özelliği vardır, çünkü ForeignKey ve Airline'ın idAirlineFlights özelliği yoktur. Bu, AirlineFlights'ı sahip / tanımlayan varlık yapar mı?

Teorik olarak, havayolunun havayolu şirketinin sahibi olmasını istiyorum.

resim açıklamasını buraya girin

Yanıtlar:


151

@JoinColumnHer iki modeli de belirterek iki yönlü bir ilişkiniz olmaz. İki tek yönlü ilişkiniz var ve bu konuda çok kafa karıştırıcı bir haritaya sahipsiniz. Her iki modele de IDAIRLINE sütununa "sahip olduklarını" söylüyorsunuz. Gerçekten bunlardan sadece biri gerçekten olmalı! 'Normal' bir şey almaktır @JoinColumnarasında kapalı @OneToManytamamen tarafında ve bunun yerine kadar mappedBy ekleyin @OneToMany.

@OneToMany(cascade = CascadeType.ALL, mappedBy="airline")
public Set<AirlineFlight> getAirlineFlights() {
    return airlineFlights;
}

Bu, Hazırda Bekletme "Git, yapılandırmayı bulmak için bir koleksiyona sahip olduğum şeye 'havayolu' adlı fasulye özelliğine bakın.


2
Sonunda mappedBy ile ilgili açıklamanızla biraz kafam karıştı. İşlerin db'de nasıl düzenlendiği önemli mi? @DB: AirlineFlights, Yabancı Anahtar olarak idAirline'a sahiptir. Havayolu, birincil anahtar olarak idAirline'a sahiptir ve AirlineFlights @ DB hakkında bilgi sağlamaz.
brainydexter

10
Evet, önemli. MappedBy içindeki ad Hazırda Beklet'e JoinColumn için yapılandırmanın nerede bulunacağını bildirir. (AirlineFlight ait getAirline () yöntemine günü.) Bu arada, sen o Havayolu anlatıyorsun havayoluyla JoinColumn koyarak eşledikten olan diğer tablodaki üzerinde değerleri bakımından sorumlu. Bir Varlığa farklı bir tabloda bir sütunun "sahibi" olduğunu söylemek ve onu güncellemekten sorumludur. Genellikle yapmak istediğiniz bir şey değildir ve SQL ifadelerinin yürütüldüğü sırada sorunlara neden olabilir.
Affe

Lütfen düzenlemeye bakın. DB düzeyinde, airlineFlight tablosu idAirline'a yabancı anahtar sütunu olarak sahiptir. Bu nedenle JoinColumn, ilgili sütuna sahip olduğu için ilgili ManytoOne içinde airlineFlight sınıfına / tablosuna konulmalıdır?
brainydexter

Evet, bu şekilde yapmanızı tavsiye ederim. En az karmaşık seçenektir ve başka bir şeye ihtiyaç duymuyorsunuz.
Affe

"@JoinColumn'u @OneToMany tarafından tamamen çıkarın" demek istediğin @ManyToOnetaraf, değil mi?
nbro

284

MappedBy sinyalleri, ilişkinin anahtarının diğer tarafta olduğunu hazırda bekletir.

Bu, 2 tabloyu birbirine bağlamanıza rağmen, bu tablolardan yalnızca 1 tanesinin diğerine yabancı bir kısıtlaması olduğu anlamına gelir. MappedBy, kısıtlama içermeyen tablodan diğer tabloya bağlantı kurmanıza izin verir.


3
biraz daha açıklar mısınız?
Alexander Suraphel

1
@Kurt Du Bois, neden mappedByiki yönlü tanımlamak yerine (her iki tarafta da yabancı_anahtar kısıtlamaları olan)?
Kevin Meredith

6
Çünkü bazen her iki tarafa da anahtar koymak mantıklı değil. Diyelim ki bir şirketiniz ve portatifiniz var. Bir taşınabilir cihaz yalnızca bir şirkete ait olacaktır, ancak bir şirketin birden fazla taşınabilirliği olacaktır.
Kurt Du Bois

Cevabımı geri aldığım için düzenleme görevlisine özür dilerim, ama aslında düzenlemenizde hiçbir katma değer yoktu. Son cümle anlamlı değildi.
Kurt Du Bois

@KurtDuBois kadar eşlenen sadece nasıl veritabanı oluşturmak için nasıl resim, yani ya mappedby kullanarak veya java tarafında hazırda bekleme değil benzer şekilde davranır.

22

mappedbykendisi için konuşursa, kış uykusuna bu alanı eşlememesini söyler. zaten bu alan [map = "field"] tarafından eşlendi.
alan diğer varlıkta(name of the variable in the class not the table in the database) ..

Bunu yapmazsanız, hazırda bekletme aynı ilişki olmadığı için bu iki ilişkiyi eşler

bu yüzden hazırda bekletme işlemini eşleştirmeyi yalnızca bir tarafta yapmasını ve aralarında koordinasyon yapmasını söylemeliyiz.


isteğe bağlıdır? Çünkü mappedBy kullanmadan aynı sonucu alıyorum yani çift yönlü nesne haritalama
Freelancer

Eğer bir tarafta mappedBy kullanmak zorunda many2many yan aynı şeyi birinde mappedBy kullanmadan on2many ve many2one kullanamazsınız
Charif DZ

Diğer değerdeki alanın adı olan özellik değerinin ne anlama geldiğini belirttiğiniz için teşekkür ederiz.
Gab 是 好人

2
Belki hazırda bekletme her zaman kendisi için konuşmaz, ama en azından noktalama işaretlerini kullanır
Amalgovinus

1
Benim için, kendisi için konuşmuyor; tersine, çok kafa karıştırıcı. Sadece ne olduğuna dair soru miktarına bakın mappedByve inversedBy. Diğer ORMS'nin çok daha zeki kullanmak belongsToMany, hasManybağlıyor.
Jan Bodnar

12

mappedby = "başka bir sınıfta yaratılmış aynı sınıftaki varlık nesnesi"

Not: -Mapped by, yalnızca bir sınıfta kullanılabilir çünkü bir tablo yabancı anahtar kısıtlaması içermelidir. Eğer eşlenirse her iki tarafa da uygulanabilirse, yabancı anahtarı her iki tablodan da kaldırır ve yabancı anahtar olmadan iki tablo b / w ilişkisi yoktur.

Not: - aşağıdaki ek açıklamalar için kullanılabilir: - 1. @ OneTone 2. @ OneToMany 3. @ ManyToMany

Not --- Aşağıdaki açıklama için kullanılamaz: - 1. @ ManyToOne

Bire bir: - Eşlemenin herhangi bir tarafında gerçekleştirin, ancak yalnızca bir tarafta gerçekleştirin. Sınıfın uygulandığı tabloda fazladan yabancı anahtar kısıtlaması sütununu kaldıracaktır.

Örneğin. Çalışan sınıfında çalışan nesnesine eşlenmiş olarak uygularsak, Çalışan tablosundaki yabancı anahtar kaldırılır.


12

Tablo ilişkisi ve varlık ilişkisi

İlişkisel veritabanı sisteminde, one-to-manytablo ilişkisi aşağıdaki gibi görünür:

<code> bire çok </code> tablo ilişkisi

İlişkinin, post_idalt tablodaki Yabancı Anahtar sütununa (ör. ) Dayandığını unutmayın.

Dolayısıyla, bir one-to-manytablo ilişkisini yönetmek söz konusu olduğunda tek bir gerçek kaynağı vardır .

Şimdi, one-to-manydaha önce gördüğümüz tablo ilişkisini eşleyen iki yönlü bir varlık ilişkisi alırsanız :

Çift yönlü <code> Bire Çok </code> varlık ilişkisi

Yukarıdaki şemaya bakarsanız, bu ilişkiyi yönetmenin iki yolu olduğunu görebilirsiniz.

Gelen Postvarlık, sahip commentskoleksiyon:

@OneToMany(
    mappedBy = "post",
    cascade = CascadeType.ALL,
    orphanRemoval = true
)
private List<PostComment> comments = new ArrayList<>();

Ve içinde PostComment, postaşağıdaki gibi ilişki eşleştirilir:

@ManyToOne(
    fetch = FetchType.LAZY
)
@JoinColumn(name = "post_id")
private Post post;

Yabancı Anahtar sütununu temsil etmenin iki yolu olduğundan, ilişkilendirme durumu değişikliğini eşdeğer Yabancı Anahtar sütun değeri değişikliğine çevirirken gerçekliğin hangisinin olduğunu tanımlamanız gerekir.

MappedBy

Bu mappedByözellik,@ManyToOne yan Yabancı anahtar sütunu yönetiminden sorumlu olduğunu ve toplama çocuk varlığı getirilemiyor sadece kullanıldığı ve çocuklara kaskad ana varlık devlet değişikliklere (örneğin aynı zamanda çocuk varlıkları kaldırmalısınız ebeveyn kaldırma).

İki yönlü bir ilişkilendirmenin her iki tarafını senkronize etme

Şimdi, mappedByözelliği tanımlasanız ve alt taraf @ManyToOneilişkilendirmesi Yabancı Anahtar sütununu yönetse bile, çift yönlü ilişkilendirmenin her iki tarafını da eşitlemeniz gerekir.

Bunu yapmanın en iyi yolu şu iki yardımcı program yöntemini eklemektir:

public void addComment(PostComment comment) {
    comments.add(comment);
    comment.setPost(this);
}

public void removeComment(PostComment comment) {
    comments.remove(comment);
    comment.setPost(null);
}

addCommentVe removeCommentyöntemler her iki taraf senkronize olduğundan emin olun. Dolayısıyla, bir alt öğe eklersek, alt öğenin ana öğeye işaret etmesi gerekir ve ana öğenin alt öğenin alt öğe koleksiyonunda bulunması gerekir.

Tüm çift yönlü varlık ilişkilendirme türlerini senkronize etmenin en iyi yolu hakkında daha fazla bilgi için bu makaleye göz atın .


0

ManyToOne eşlemesine başladınız, sonra OneToMany eşlemesini de Çift Yönlü yol için koydunuz. Daha sonra OneToMany tarafında (genellikle üst tablonuz / sınıfınız), "mappedBy" (eşleme tarafından ve alt tablo / sınıf tarafından yapılır) belirtmeniz gerekir, bu nedenle hazırda bekletme modu DB'de EXTRA eşleme tablosu oluşturmaz (TableName = parent_child gibi).

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.