Związki między encjami w
standardzie Java Persistence
Wykład jest oparty na:
[1] JSR-000317 JavaTM Persistence 2.0 ("Specification")
(https://jcp.org/aboutJava/communityprocess/final/jsr317/)
[2] The Java EE 7 Tutorial
(http://docs.oracle.com/javaee/7/tutorial/doc/)
Michał Bleja
Plan
●
Wprowadzenie do JPA (ang. Java Persistence API)
●
Charakterystyka klas encji
●
Odwzorowanie klas encji i ich atrybutów
●
Rodzaje relacji między encjami
●
Adnotacje modelujące relacje
Wprowadzenie do Java Persistence API
●
Mechanizm do zarządzania trwałością w aplikacjach Java
SE oraz Java EE
●
Realizuje odwzorowanie obiektowo-relacyjne
●
Pozwala programiście używać dziedzinowego modelu
języka Java w celu zarządzania relacyjnymi bazami
danych
Główne elementy standardu Java Persistence
●
Java Persistence API
●
Język zapytań JPQL (Java Persistence Query Language)
●
Metadane o odwzorowaniu relacyjno-obiektowym
Encje (ang. entities)
●
Encje reprezentują trwałe dane przechowywane w
relacyjnej bazie danych.
●
Typowo encje utożsamia się z tabelą a jej wystąpienia
(instancje) reprezentują poszczególne wiersze tabeli
●
Trwały stan encji jest wyznaczony przez jej pola lub
właściwości
●
Artefaktem reprezentującym encje jest klasa encji
Przykład encji
@Entity //wskazanie, że rozważana klasa jest encją
public class Employee {
@Id //wskazuje, że pole id składuje trwałą tożsamość
//encji (klucz główny)
private int id;
private String name;
private long sal;
public Employee() {}
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) {
this.name = name; }
public long getSal() { return sal; }
public void setSal(long sal) {this.sal = sal; }
}
Adnotacje trwałości
●
Dostarczają mechanizmu odwzorowania obiektowo
relacyjnego
●
Mogą być stosowane na trzech różnych poziomach (klasy,
metody, pola)
●
Są umieszczane przed kodem źródłowym adnotowanego
artefaktu
●
Pozwalają odwzorować stan obiektu w bazie danych
●
Umożliwiają formułowanie zapytań adresujących obiekty
klas encji
Dostęp do stanu encji
Dostęp w oparciu o pola
(ang. field access)
Dostęp w oparciu o właściwości
(ang. property access)
@Entity
public class Employee {
@Id private int id;
private String name;
private long sal;
public Employee() {}
public int getId() {
return id; }
public void setId(int id) {
this.id = id; }
...
}
@Entity
public class Employee {
private int id;
private String name;
private long sal;
public Employee() {}
@Id public int getId()
return id; }
public void setId(int id) {
this.id = id; }
...
}
Odwzorowanie tabeli
●
Adnotacja @Table pozwala wyspecyfikować tabelę dla
encji
●
Adnotacja @Column określa odwzorowanie kolumny na trwałą
właściwość lub pole w klasie encji
@Table(name = "EMP")
public class Employee {
@Id
@Column(name="EMP_ID", nullable = false)
private Long empId;
@Column(nullable = false, length = 25)
private String fName;
@Column(nullable = false, length = 35)
private String lName;
@Column(length = 40)
private String address;
…
}
Związki między encjami
Encje wchodzą ze sobą w związki charakteryzujące się określonymi
cechami (np. kierunkowość, liczebność, istnienie)
Implementacja związku
Encja będąca uczestnikiem związku posiada atrybut, który wskazuje
encję z nią powiązaną.
Kierunkowość
●
Jeśli tylko jedna encja posiada wskaźnik do drugiej wtedy związek
jest jednokierunkowy
●
Jeśli encje uczestniczące w związku wskazują na siebie nawzajem
wówczas związek jest dwukierunkowy (rozważa się go jako parę
związków jednokierunkowych)
Employee
Department
Employee
Car
Związki między encjami
Związki dwukierunkowe mają zarówno stronę właścicielską (ang.
owning side) oraz stronę przeciwną (ang. inverse side).
Związki jednokierunkowe mają tylko stronę właścicielską.
Liczebność związku określa ile instancji danej encji może być
powiązanych z iloma wystąpieniami innej encji.
Wyróżniamy następujące rodzaje relacji (odzwierciedlają one nazwy
adnotacji:
●
Many – to – one
●
One – to – one
●
One- to – many
●
Many – to – Many
*
1
1 1
Employee
Department
Car
Employee
Dwukierunkowa relacja typu One-to-One
strona właścicielska (ang. owning side) –
strona zawierająca klucz obcy
strona przeciwna (ang. inverse side) –
odnosi się do strony właścicielskiej poprzez
element mappedBy
@Entity
public class Employee{
@id private int id;
@OneToOne
//odwzorowanie klucza obcego
@JoinColumn(name=
"CAR
_ID
"
)
private Car car;
…
}
@Entity
public class Car{
@id private int id;
/* wartością mappedBy jest
nazwa atrybutu w encji
właścicielskiej,który
wskazuje na encje
przeciwną */
@OneToOne(mappedBy=
"car"
)
private Employee emp;
…
}
Dwukierunkowe relacje typu Many-to-One/One-to-Many
strona właścicielska
strona przeciwna
@Entity
public class Employee{
@id private int id;
@ManyToOne
//odwzorowanie klucza
// obcego
@JoinColumn(name=
"DEPT
_ID
"
)
private Department dept;
…
}
@Entity
public class Department{
@id private int id;
private String name;
@OneToMany(mappedBy=
"dept"
)
private Collection<Employee>
emps;
…
}
Strona N związku 1:N/N:1 musi być stroną właścicielską, stąd element
mappedBy nie może być określony na adnotacji ManyToOne
Dwukierunkowa relacje typu Many-to-Many
(każda ze stron może być stroną właścicielską)
@Entity
public class Student{
@id private int sid;
@ManyToMany
@JoinTable(name=
"Student
_Organization
",
(name=STUDENTS_SID),
inverse
JoinColumns=@JoinColumn
(name=ORGANIZATIONS_OID))
p
rivate Collection<Organizations> organizations;
…
}
@Entity
public class Organization{
@id private int oid;
@ManyToMany(
mappedBy=
"
organizations
"
)
p
rivate Collection<Student> students;
…
}
Jednokierunkowa relacja typu One-to-One
@Entity
public class Employee{
@id private int id;
@OneToOne
@JoinColumn(name="CAR_ID") //odwzorowanie klucza obcego
private Car car;
…
}
@Entity
public class Car{
@id private int id;
…
//brak referencji do instancji klasy Employee
}
Jednokierunkowa relacja typu Many-to-One
@Entity
public class Employee{
@id private int id;
@ManyToOne
@JoinColumn(name=
"DEPT
_ID
"
) // odwzorowanie klucza obcego
private Department dept;
…
}
@Entity
public class Department{
@id private int id;
// brak referncji do kolekcji instancji klasy Employee
…
}
Jednokierunkowa relacja typu One-to-Many
(domyślne odwzorowanie)
@Entity
public class
Department
{
@id private int id;
@OneToMany
@JoinTable(name=
"Department
_Employee
",
(name=DEPARTMENT_ID),
inverse
JoinColumns=@JoinColumn
(name=EMPLOYEE_ID))
private Collection<Employee> emps
;
… }
@Entity
public class Employee{
@id private int id;
// brak referencji do instancji klasy Department
…
}
Jednokierunkowa relacja typu One-to-Many
(odwzorowanie z użyciem klucza obcego)
@Entity
public class
Department
{
@id private int id;
@OneToMany
@JoinColumn(name=
"DEPT
_ID
"
) // odwzorowanie klucza obcego
private Collection<Employee> emps
;
…
}
@Entity
public class Employee{
@id private int id;
// brak referencji do instancji klasy Department
…
}
Jednokierunkowa relacja typu Many-to-Many
@Entity
public class Student{
@id private int sid;
@ManyToMany
@JoinTable(name=
"Student
_Organization
",
(name=STUDENTS_SID),
inverse
JoinColumns=@JoinColumn
(name=ORGANIZATIONS_OID))
p
rivate Collection<Organizations> organizations;
…
}
@Entity
public class Organization{
@id private int oid;
// brak referencji do kolekcji instancji klasy Student
;
…
}
Podsumowanie
●
JPA dostarcza siedem typów relacji między encjami (cztery
jednokierunkowe, trzy dwukierunkowe)
●
Istnienie relacji implikuje zastosowanie odpowiedniej
adnotacji modelującej związek
●
Adnotacje odzwierciedlają praktykę stosowaną w
modelowaniu schematów relacyjnych
●
Odwzorowania domyślne upraszczają kod źródłowy