enterprise javabeans (ejb) - relacije.pdf · 3/44 referencijalni integritet • u okviru anotacija...
TRANSCRIPT
Relacije
2/44
Relacije
• Četiri vrste: – OneToOne
• Radnik - Polisa osiguranja
• Person - Home address
– ManyToOne • Radnik - Radno mesto
• Bank account - Person
– OneToMany • Radno mesto - Radnik
• Manager - Employees
– ManyToMany • Nastavnik - Predmet
• Email list - Subscriber
3/44
Referencijalni integritet
• U okviru anotacija stavlja se atribut cascade sa skupom vrednosti: – CascadeType.PERSIST
• poziva persist operaciju nad povezanim objektom prilikom perzistiranja ovog objekta
– CascadeType.MERGE
• poziva merge operaciju nad povezanim objektom prilikom pozivanja merge nad ovim objektom
– CascadeType.REMOVE
• poziva remove operaciju nad povezanim objektom prilikom pozivanja remove nad ovim objektom
– CascadeType.REFRESH
• poziva refresh operaciju nad povezanim objektom prilikom pozivanja refresh nad ovim objektom
– CascadeType.ALL
• sve četiri varijante zajedno
4/44
OneToOne
• Atribut koji ukazuje na drugi entity,
označava se anotacijom @OneToOne
• Radnik– Polisa osiguranja
5/44
Radnik.java
@Entity
public class Radnik{
@Id
private int id;
private String ime, prezime;
@OneToOne(cascade={CascadeType.ALL})
private PolisaOsiguranja polisa;
public int getId() {
return id;
}
public PolisaOsiguranja getPolisa() {
return polisa;
}
...
}
6/44
PolisaOsiguranja.java
@Entity
public class PolisaOsiguranja{
@Id
private int id;
private String nazivPolise;
private double iznos;
public int getId() {
return id;
}
...
}
7/44
Tabele
PolisaOsiguranja
Radnik
8/44
RadnikCrud.java public Radnik insertRadnikPolisa(Radnik r){
EntityManager em = PersistenceUtil.getEntityManager();
EntityTransaction et = null;
Radnik retVal = null;
try{
et = em.getTransaction();
et.begin();
em.persist(r);
em.flush();
et.commit();
retVal = r;
}catch(Exception ex){ //RuntimeException
ex.printStackTrace();
if(et != null){
et.rollback();
}
}finally{
if(em != null && em.isOpen()){
em.close();
}
}
return retVal;
}
9/44
RadnikCrud.java
public List<Radnik> getLista(){
EntityManager em =
PersistenceUtil.getEntityManager();
String query = "select r from Radnik r";
List<Radnik> retVal =
em.createQuery(query).getResultList();
em.close();
return retVal;
}
10/44
OneToOneTest.java
RadnikCrud rc = new RadnikCrud();
PolisaOsiguranja p = new PolisaOsiguranja(1234, "zivotno osiguranje", 12345);
Radnik r = new Radnik(2, "Maja", "Maric", p);
rc.insertRadnikPolisa(r);
11/44
Many to one
• Atribut koji ukazuje na drugi entity,
označava se anotacijom @ManyToOne
• Radnik– Radno mesto
12/44
Radnik.java @Entity(name="Radnik2")
@Table(name="Radnik2")
public class Radnik {
@Id
private int mbr;
private String ime, prezime;
@ManyToOne (cascade={CascadeType.REFRESH})
private RadnoMesto radnoMesto;
...
public int getMbr() {
return mbr;
}
...
public void setRadnoMesto(RadnoMesto radnoMesto) {
this.radnoMesto = radnoMesto;
}
}
Ako imamo istoimenu klasu, ovim joj dajemo
drugo ime za persistence context
13/44
RadnoMesto.java
@Entity
@Table(name="RadnoMesto")
public class RadnoMesto {
@Id
private int idrm;
private String naziv;
...
}
14/44
Tabele
RadnoMesto
Radnik
15/44
RadnikRadnoMestoCrud.java public void poveziRadnikaIRadnoMesto(Radnik r, RadnoMesto
rm){
EntityManager em = PersistenceUtil.getEntityManager();
EntityTransaction et = null;
try {
et = em.getTransaction();
et.begin();
r.setRadnoMesto(rm); em.merge(r);
em.merge(rm);
em.flush();
et.commit();
} catch (RuntimeException ex) {
if(et != null)
et.rollback();
ex.printStackTrace();
} finally {
if(em != null && em.isOpen())
em.close();
}
}
16/44
ManyToOneTest.java
...
RadnikRadnoMestoCrud rrmc = new RadnikRadnoMestoCrud();
...
rm1 = new RadnoMesto(1, "programer");
...
r1 = new Radnik(1, "Pera", "Perić");
...
rrmc.poveziRadnikaIRadnoMesto(r1, rm1);
...
17/44
One to many
• Kolekcija koja ukazuje na druge entity-je,
označava se anotacijom @OneToMany
• Osoba – Bankovni račun
18/44
Osoba.java
@Entity
@Table(name="Osoba")
public class Osoba implements java.io.Serializable {
@Id
private int idOsobe;
private String ime, prezime;
@OneToMany(cascade={CascadeType.ALL})
private Collection<BankovniRacun> racuni;
public int getIdOsobe() {
return idOsobe;
}
public Collection <BankovniRacun> getRacuni() {
return racuni;
}
...
}
19/44
BankovniRacun.java
@Entity
@Table(name="BankovniRacun")
public class BankovniRacun implements
java.io.Serializable {
@Id
private int brojRacuna;
private String naziv;
private double iznos;
public int getBrojRacuna() {
return brojRacuna;
}
...
}
20/44
Tabele – jednosmerna veza
Osoba
BankovniRacun
Osoba_BankovniRacun
21/44
Čime je veza ograničena na one to
many?
• Ako imamo veznu tabelu, čime je
sprečeno da dodamo jednom računu još
jednog vlasnika?
22/44
Fetch
• FetchType.LAZY – default za LOB i veze tipa kolekcija (kardinalitet n)
– dovućiće iz baze objekte iz veze, rekurzivno, samo ako je potrebno
• FetchType.EAGER – default za primitivne tipove i veze tipa referenca (kardnalitet 1)
– dovlači sve objekte iz veze, rekurzivno
– manje efikasno
– ako dovlačimo jednim upitom objekte sa vezama na klijenta (preko serijalizacije), ovo je neophodno
• Može se podesiti na nivou upita koji atribut se dovlači odmah, a koji kasnije – fetch join
23/44
Bidirekciona veza
• Ako je veza u oba smera, tada moramo da kod klase Osoba naglasimo koji atribut u BankovniRacun klasi ukazuje na njega (mappedBy atribut anotacije) u drugom smeru.
• Primer: @OneToMany(cascade={CascadeType.ALL},
fetch=FetchType.EAGER,
mappedBy="vlasnik")
public Collection <BankovniRacun> racuni; -----------------------------------------------------------------------------------------------------------------------------------
@ManyToOne(cascade={CascadeType.REFRESH})
private Osoba vlasnik;
24/44
Osoba.java
@Entity
@Table(name="Osoba")
public class Osobaimplements java.io.Serializable {
@Id
private int idOsobe;
private String ime, prezime;
@OneToMany(cascade={CascadeType.ALL},
fetch=FetchType.EAGER,
mappedBy="vlasnik")
private Collection<BankovniRacun> racuni;
public int getIdOsobe() {
return idOsobe;
}
public Collection <BankovniRacun> getRacuni() {
return racuni;
}
...
}
25/44
BankovniRacun.java
@Entity
@Table(name="BankovniRacun")
public class BankovniRacun implements java.io.Serializable {
@Id
private int brojRacuna;
private String naziv;
private double iznos;
@ManyToOne(cascade={CascadeType.REFRESH})
private Osoba vlasnik;
public int getBrojRacuna() {
return brojRacuna;
}
public Osoba getVlasnik() {
return Vlasnik;
}
...
}
26/44
Tabele – dvosmerna veza
Osoba
BankovniRacun
27/44
OsobaCrud.java public static void insertOsobaIRacuni(Osoba o){
...
em.persist(o);
...
}
...
BankovniRacun racun1 = new BankovniRacun(1, 1234.00, "dinarski racun");
BankovniRacun racun2 = new BankovniRacun(2, 432.00, "devizni racun");
ArrayList<BankovniRacun> racuni = new ArrayList<BankovniRacun>();
racuni.add(racun1);
racuni.add(racun2);
Osoba o = new Osoba(1, "Ana", "Peric");
o.setRacuni(racuni);
OsobaCrud.insertOsobaIRacuni(o);
28/44
OsobaCrud.java
public void dodajRacun(Osoba o, BankovniRacun r) throws Exception{
Query q = em.createQuery("select o from Osoba o where o.idOsobe = :id");
q.setParameter("id", o.getIdOsobe());
List <Osoba> res = q.getResultList();
if (res.size() == 0) {
// ne postoji osoba
throw new Exception("Osoba sa id-om: " + o.getIdOsobe() + " ne postoji!");
} else {
Osoba o = res.get(0);
o.getRacuni().add(r);
}
}
29/44
Dvosmerna veza i brisanje
• Ako je veza dvosmerna i leva strana ima
kolekciju/listu objekata desne strane, prilikom
brisanja desnog entiteta, potrebno je da se
obriše iz kolekcije levog entitija, pre brisanja.
• Ako entiti nije bio u managed stanju, mora se
prvo uraditi merge, pa se onda briše:
e = em.merge(e);
em.remove(e);
30/44
Many to many
• Kolekcija koja ukazuje na druge entity-je,
označava se anotacijom @ManyToMany
• Sistem će automatski napraviti poveznu
tabelu
• Nastavnik – Predmet
31/44
Nastavnik.java
@Entity
@Table(name="Nastavnik")
public class Nastavnik implements java.io.Serializable {
@Id
private int id;
private String ime, prezime, zvanje;
@ManyToMany(cascade={})
private Collection<Predmet>predmeti = new ArrayList<Predmet>();
public int getId() {
return id;
}
public Collection <Predmet> getPredmeti() {
return predmeti;
}
...
}
32/44
Predmet.java
@Entity
@Table(name="Predmet")
public class Predmet implements java.io.Serializable {
@Id
private int id;
private String naziv;
@ManyToMany(cascade={}, mappedBy="predmeti")
private Collection<Nastavnik> nastavnici = new ArrayList<Nastavnik>();
public int getId() {
return id;
}
public Collection <Nastavnik> getNastavnici() {
return nastavnici;
}
...
}
33/44
Tabele Nastavnik
Predmet
Predmet_Nastavnik
34/44
NastavnikPredmetCrud.java
public void napraviNastavnika(Nastavnik n) {
...
em.persist(s);
...
}
public void napraviPredmet(Predmet p) {
...
em.persist(c);
...
}
35/44
NastavnikPredmetCrud.java public void poveziNastavnikaIPredmet(Nastavnik n, Predmet p){
EntityManager em = PersistenceUtil.getEntityManager();
EntityTransaction et = null;
try {
et = em.getTransaction();
et.begin();
n.getPredmeti().add(p);
p.getNastavnici().add(n);
em.merge(n);
em.merge(p);
em.flush();
et.commit();
} catch (RuntimeException ex) {
if(et != null)
et.rollback();
ex.printStackTrace();
} finally {
if(em != null && em.isOpen())
em.close();
}
}
36/44
ManyToManyTest.java Nastavnik n1 = new Nastavnik(1, "Pera", "Perić", "docent");
Nastavnik n2 = new Nastavnik(2, "Mika", "Mikić", "redovni profesor");
NastavnikCrud nc = new NastavnikCrud();
nc.persist(n1);
nc.persist(n2);
List<Nastavnik> listaN = snc.getLista();
for (Nastavnik n : listaN) {
System.out.println(n);
}
PredmetCrud pc = new PredmetCrud();
Predmet p1 = new Predmet(1, "Baze podataka 1");
Predmet p2 = new Predmet(2, "Baze podataka 2");
pc.persist(p1);
pc.persist(p2);
List<Predmet> listaP = pc.getLista();
for (Predmet p : listaP) {
System.out.println(p);
}
NastavnikPredmetCrud npc = new NastavnikPredmetCrud();
npc.poveziNastavnikaIPredmet(n1, p1);