Jestem nowy w hibernacji i muszę używać relacji jeden do wielu i wiele do jednego. Jest to relacja dwukierunkowa w moich obiektach, dzięki czemu mogę przechodzić z dowolnego kierunku. mappedBy
jest zalecanym sposobem, aby się do tego zabrać, jednak nie mogłem tego zrozumieć. Czy ktoś może wyjaśnić:
- jaki jest zalecany sposób korzystania z niego?
- jaki cel to rozwiązuje?
Ze względu na mój przykład, oto moje zajęcia z adnotacjami:
Airline
POSIADA wieluAirlineFlights
- Wielu
AirlineFlights
należy do JEDNEGOAirline
Linia lotnicza :
@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;
}
}
Linie lotnicze:
@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);
}
}
EDYTOWAĆ:
Schemat bazy danych:
AirlineFlights ma idAirline jako ForeignKey, a Airline nie ma idAirlineFlights. To sprawia, że AirlineFlights jest właścicielem / podmiotem identyfikującym?
Teoretycznie chciałbym, aby właścicielem linii lotniczych były linie lotnicze.
źródło
@ManyToOne
stronę, prawda?MappedBy sygnalizuje hibernację, że klucz do relacji znajduje się po drugiej stronie.
Oznacza to, że chociaż łączysz ze sobą 2 tabele, tylko jedna z nich ma ograniczenie związane z kluczem obcym do drugiej. MappedBy pozwala nadal łączyć się z tabelą niezawierającą ograniczenia do innej tabeli.
źródło
mappedBy
zamiast definiować dwukierunkowy (z ograniczeniami obcego klucza po każdej stronie)?mappedby
mówi sam za siebie, mówi hibernacji, aby nie mapować tego pola. jest już zmapowane przez to pole [nazwa = "pole"].pole znajduje się w drugiej jednostce
(name of the variable in the class not the table in the database)
.więc musimy powiedzieć hibernacji, aby wykonała mapowanie tylko z jednej strony i skoordynować między nimi.
źródło
mappedBy
iinversedBy
. Inne ORMs używać dużo bardziej inteligentnybelongsToMany
,hasMany
atrybuty.mappedby = "obiekt podmiotu tej samej klasy utworzony w innej klasie"
Uwaga: -Mapowane przez może być używane tylko w jednej klasie, ponieważ jedna tabela musi zawierać ograniczenie klucza obcego. jeśli mapowane przez można zastosować po obu stronach, to usuwa klucz obcy z obu tabel, a bez klucza obcego nie ma relacji między dwiema tabelami.
Uwaga: - można go używać do następujących adnotacji: - 1. @ OneTone 2. @ OneToMany 3. @ ManyToMany
Uwaga --- Nie można jej używać do następujących adnotacji: - 1. @ ManyToOne
W jeden do jednego: - Wykonuj po dowolnej stronie mapowania, ale wykonuj tylko po jednej stronie. Spowoduje to usunięcie dodatkowej kolumny ograniczenia klucza obcego w tabeli, do której jest stosowane.
Np. Jeśli zastosujemy mapowanie by w klasie Employee na obiekcie pracownika, to klucz obcy z tabeli Employee zostanie usunięty.
źródło
Relacja między tabelami a relacja encji
W systemie relacyjnej bazy danych relacja między
one-to-many
tabelami wygląda następująco:Zauważ, że relacja jest oparta na kolumnie Foreign Key (np.
post_id
) W tabeli podrzędnej.Tak więc istnieje jedno źródło prawdy, jeśli chodzi o zarządzanie
one-to-many
relacjami między stołami.Teraz, jeśli weźmiesz dwukierunkową relację encji, która mapuje na
one-to-many
relację między tabelami, którą widzieliśmy wcześniej:Jeśli spojrzysz na powyższy diagram, zobaczysz, że istnieją dwa sposoby zarządzania tą relacją.
W
Post
jednostce maszcomments
kolekcję:A w
PostComment
Thepost
stowarzyszenie jest odwzorowany w sposób następujący:Ponieważ istnieją dwa sposoby przedstawiania kolumny klucza obcego, należy określić, który jest źródłem prawdy, jeśli chodzi o tłumaczenie zmiany stanu skojarzenia na odpowiadającą jej modyfikację wartości kolumny klucza obcego.
MappedBy
mappedBy
Atrybut informuje, że@ManyToOne
strona jest odpowiedzialna za zarządzanie kolumny klucz obcy, a zbiór jest używany tylko do pobierania jednostek podrzędnych i kaskady zmian stanu podmiotem dominującym dla dzieci (na przykład usuwając rodzic powinien także usunąć podmioty podrzędne).Zsynchronizuj obie strony skojarzenia dwukierunkowego
Teraz, nawet jeśli zdefiniowałeś
mappedBy
atrybut i@ManyToOne
powiązanie po stronie podrzędnej zarządza kolumną klucza obcego, nadal musisz zsynchronizować obie strony skojarzenia dwukierunkowego.Najlepszym sposobem na to jest dodanie dwóch metod narzędziowych:
addComment
IremoveComment
metody zapewnienia, że obie strony są zsynchronizowane. Tak więc, jeśli dodamy jednostkę podrzędną, jednostka podrzędna musi wskazywać na jednostkę nadrzędną, a jednostka nadrzędna powinna zawierać element podrzędny w kolekcji podrzędnej.źródło
Zacząłeś od mapowania ManyToOne, a następnie umieściłeś mapowanie OneToMany również w trybie dwukierunkowym. Następnie po stronie OneToMany (zwykle twoja tabela / klasa nadrzędna), musisz wspomnieć o „mappedBy” (mapowanie jest wykonywane przez iw tabeli / klasie potomnej), więc hibernacja nie utworzy tabeli mapowania EXTRA w DB (jak TableName = parent_child).
źródło