programmazione java avanzata - unirc.it · programmazione java avanzata hibernate (parte 2) ing....

76
Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aquì

Upload: doanhanh

Post on 27-Apr-2018

237 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

Programmazione Java Avanzata

Hibernate (Parte 2)

Ing. Giuseppe D'Aquì

Page 2: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

2

Testi Consigliati● Beginning Hibernate 2nd edition (Apress)

● Sul sito è possibile scaricare, tra gli “extra”, il codice sorgente e il capitolo 3

● Hibernate Getting Started● http://docs.jboss.org/hibernate/core/3.6/quickstart/en-US/html_single/

Page 3: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

3

Pro e contro Annotations● Pro:

● Le annotation sono standard JPA, quindi sono usate in modo identico da tutti gli ORM JPA-compatibili

● Meno verbosità● Intuitive

● Contro:● Le versioni obsolete di Hibernate supportano solo

XML● Se il database è usato da più applicazioni, si rischia

di distribuire il mapping su applicazioni diverse

Page 4: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

4

Chiave Composta● Se in una tabella la chiave primaria è

costituita da più campi, si ha una chiave composta

● Quando non ci sono particolari vincoli (ovvero abbiamo il controllo dello schema del database), in genere si preferisce semplificare lo sviluppo generando una chiave surrogata● Una chiave surrogata non ha significato al di fuori

del database, è un campo che rimpiazza i molti campi della chiave composta

Page 5: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

5

Chiave Composta● Quando però ci sono vincoli la chiave

composta deve essere mappata su Hibernate● Ci sono tre modalità, tutte e tre prevedono la

creazione di una classe che contenga il mapping dei campi della chiave composta● Es. se la chiave composta è (nome, cognome),

allora serve una classe (differente dalla corrente) che contenga come variabili membro String nome e String cognome

Page 6: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

6

Chiave composta: modo 1● La classe con gli attributi chiave deve essere

pubblica ed esterna ● public class UserPrimaryKey{...}

● La classe va annotata con @Embeddable, e devono essere implementati i metodi hashCode() ed equals()

● Nella classe originaria, invece, bisogna sostituire gli attributi della chiave composta con un unica variabile “id” (annotata con @Id)● private UserPrimaryKey id;

Page 7: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

7

Chiave composta: modo 2● La classe con gli attributi chiave va creata

come nel modo 1, ma internamente alla classe originaria

● La classe non va annotata con @Embeddable● La classe originaria ha sempre la variabile “id”

ma annotata con @EmbeddedId

Page 8: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

8

Chiave composta: modo 3● La classe con gli attributi chiave va creata

come nel modo 2 ● Si annota solo la classe originaria con

● @IdClass● Passandogli la classe che fa le funzioni di

chiave● @IdClass(User.UserPrimaryKey.class)

● Nella classe originaria non c'è più “id” ma vanno messi gli attributi originali annotati con @Id

Page 9: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

9

Chiave composta: riassunto● Il codice SQL generato in tutti i casi è uguale● Ci sono particolarità di utilizzo:

● Modo 1: La classe con gli attributi è esterna ed embeddable (vedi relazioni one-to-one), può essere riutilizzata

● Modo 3: possiamo utilizzare gli attributi chiave direttamente dalla classe originaria [getNome() e getCognome()], invece di ottenere prima l'oggetto id

● Modo 2: una via di mezzo

Page 10: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

10

Mapping di relazioni● Le relazioni tra tabelle possono essere di

diverso tipo● One-to-One (uno-a-uno)● One-to-Many (uno-a-molti)● Many-to-Many (molti-a-molti)

Page 11: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

11

One-to-one: tipi● Le relazioni uno-a-uno, in Hibernate, sono di

due tipi:● “Classiche”, due tabelle corrispondono a

due oggetti● “Component” o “embedded”, due oggetti

che risiedono su una sola tabella (es. l'indirizzo)

Page 12: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

12

One-to-one “embedded”● Una relazione “one-to-one embedded” si ha

quando un'entità è interamente racchiusa all'interno di un'altra entità, ossia è un “componente” dell'alltra entità

● La classe “componente” va annotata con @Embeddable, non possiede @Id

● Nella classe principale viene posta una variabile membro con lo stesso tipo della classe componente, annotata con @Embedded

Page 13: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

13

One-to-one “embedded”public class User {

@Embedded

public Address getAddress(){...}

}

@Embeddable

public class Address{

private String via;

private String civico;

//getters/setters

}

Page 14: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

14

One-to-one● La relazione uno-a-uno convenzionale è in

genere “sospetta”, perché potrebbe nascondere un errore di progettazione● In genere, infatti, si tende ad accorpare tutti gli

attributi in una sola entità● Ci sono dei casi in cui, però, è preferibile

avere due tabelle che rappresentano due aspetti differenti di una certa entità “ideale”● Aspetti che devono essere gestiti differentemente,

o che devono evolvere in modo indipendente● Es. Profilo Autenticazione e Anagrafiche

Page 15: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

15

One-to-one● Per mappare una relazione uno-a-uno basta

annotare con @OneToOne la variabile membro (o il getter) che contiene l'oggetto correlato

Page 16: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

16

One-to-one “classica”public class User {

@OneToOne

public Address getAddress(){...}

}

@Entity

public class Address{

@Id

private int id;

private String via;

private String civico;

//getters/setters

}

Page 17: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

17

One-to-one● L'annotazione @OneToOne può avere i seguenti

attributi:● cascade: indica se le operazioni su una entità

devono propagarsi alle altre della relazione● fetch: indica il tipo di acquisizione, “eager”

(carica tutti gli oggetti del grafo delle relazioni) o “lazy” (carica gli oggetti correlati solo se servono)

● optional: serve per stabilire se ci possono essere NULL

Page 18: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

18

One-to-one bidirezionale● La relazione OneToOne è bidirezionale quando

l'oggetto A contiene un riferimento all'oggetto B, e l'oggetto B contiene un riferimento all'oggetto A● Es. User.getAddress() e Address.getUser()

● In questo caso uno dei due oggetti deve essere considerato “principale”● Quello la cui tabella contiene la chiave primaria

dell'altro come riferimento● L'oggetto secondario dovrà usare l'attributo

“mappedBy” nella sua annotazione @OneToOne

Page 19: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

19

One-to-one “bidirezionale”@Entity

public class User {

… //User è l'oggetto “principale”

@OneToOne

public Address getAddress(){...}

}

@Entity

public class Address{

… //Address è l'oggetto “secondario”

//il “mappedBy” si riferisce alla proprietà dell'oggetto principale

@OneToOne(mappedBy=address)

public User getUser(){...}

}

Page 20: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

20

One-to-one - JoinColumn● Per default, Hibernate cercherà come foreign

key un campo della tabella con queste caratteristiche:● Inizia con il nome della proprietà dell'oggetto

principale (User ha getAddress(), quindi “address”)● Concatenato con underscore “_”● Concatenato con il nome della chiave primaria

dell'oggetto secondario (Es, Address ha getId(), quindi “id”

● Nell'esempio quindi cercherà una colonna chiamata “address_id”

Page 21: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

21

One-to-one - JoinColumn● È possibile sovrascrivere questo default con

due tipi di annotazioni:● @PrimaryKeyJoinColumn : usato assieme a

@OneToOne sull'oggetto principale, indica che la foreign key è la stessa chiave primaria (ovvero, le due tabelle possiedono la stessa chiave primaria)

● @JoinColumn(name=”address_fk”) : usato assieme a @OneToOne sull'oggetto principale, indica che la foreign key sta in una colonna con un nome preciso (in questo caso “address_fk”)

Page 22: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

22

Cascading delle operazioni● Il cascading è la propagazione delle operazioni

di aggiornamento e rimozione su oggetti collegati tra loro da relazioni● Esempio: se viene cancellato un User deve essere

cancellato il corrispondente Address?● Hibernate definisce diversi tipi di cascading,

definiti nelle relazioni● Se non si specifica niente, per default non si

ha cascading

Page 23: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

23

Cascading delle operazioni● Tipi di cascading:

● CascadeType.MERGE : propaga gli UPDATE● CascadeType.PERSIST : propaga il primo

inserimento (INSERT)● CascadeType.REFRESH : propaga l'aggiornamento

dal database verso gli oggetti (SELECT)● CascadeType.DETACH : propaga la rimozione

dell'oggetto dalla persistenza● CascadeType.REMOVE : propaga la rimozione dei

dati dell'oggetto (DELETE)● CascadeType.ALL : tutti i precedenti

Page 24: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

24

One-to-Many● La relazione uno-a-molti può essere vista da

due “prospettive” diverse● L'oggetto A ha una relazione con molti oggetti B● Ogni oggetto B ha una relazione con uno e un solo

oggetto A● Hibernate mappa queste due prospettive

usando @OneToMany e @ManyToOne

Page 25: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

25

One-to-Many● @OneToMany va sull'oggetto che contiene● @ManyToOne va sull'oggetto contenuto● JPA considera, per convezione, “oggetto

principale” quello che ha @ManyToOne che, quindi, dovrà specificare un mappedBy

Page 26: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

26

One-to-Many@Entity

public class User {

… //User è l'oggetto “secondario”

@OneToMany(mappedBy=”user”)

public Set<Telephone> getTelephone(){...}

}

@Entity

public class Telephone{

… //Telephone è l'oggetto “principale”

@ManyToOne

public User getUser(){...}

}

Page 27: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

27

One-to-Many - JoinColumn● Valgono le stesse considerazioni di JoinColumn

fatte nel caso One-to-One● Nell'esempio Hibernate cercherà una colonna

chiamata “user_id” nella tabella “telephone” (oggetto principale)

● Possiamo però specificare un'altra colonna utilizzando @JoinColumn insieme a @ManyToOne nell'oggetto principale

Page 28: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

28

Ordering● Quando vengono mappate delle Collection,

possiamo definire una colonna sulla quale queste verranno ordinate

● @OneToMany(mappedBy=”user”)

● public List<Telephone> getTelephone(){...}

● //List è un tipo collection ordinato

● Si può aggiungere a @OneToMany l'annotazione @OrderBy, che permette di specificare quale proprietà di Telephone usare per l'ordinamento

● @OneToMany(mappedBy”user”)

● @OrderBy(“prefisso ASC”)

● public List<Telephone> getTelephone(){...}

Page 29: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

29

Many-to-Many● In una relazione Many-to-Many entrambi gli

oggetti coinvolti utilizzeranno @ManyToMany● Uno dei due deve essere l'oggetto principale,

l'altro conterrà l'attributo “mappedBy”● Una relazione molti-a-molti nel modello

relazionale ha bisogno di una tabella ausiliaria che contiene le foreign key di entrambe le tabelle

Page 30: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

30

Many-to-Many● La tabella ausiliaria ha, per default, il nome:

● Tabellaprincipale_Tabellasecondaria● E chiavi Tabellaprincipale_id e

Tabellasecondaria_id● Questi default possono essere sovrascritti con

@JoinTable, usato lato oggetto principale@JoinTable(

name=”studenti_e_corsi”,

joinColumns={@JoinColumn(name=”corso_id”)},

inverseJoinColumns{@JoinColumn(name=”matricola”)} )

Page 31: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

31

Many-to-Many: nota bene● Quando c'è una relazione molti-a-molti che

contiene attributi specifici, forse non si tratta di una mera relazione tra tabelle ma è una entità “di fatto”● Es. se la tabella Studente_Corso contiene

l'attributo “voto”, non è più una semplice tabella di join ma un'entità Esame, che ha relazioni uno-a-molti con Studente e con Corso

● La tabella di join, per Hibernate, contiene solo le foreign key e non altri attributi

Page 32: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

32

Ereditarietà● L'ereditarietà in Hibernate e JPA può essere

rappresentata in tre modi:● Single table: una singola tabella che contiene padri

e figli● Joined: una tabella per il padre e una per ciascuno

dei figli, ma i figli contengono solo gli attributi non in comune con il padre

● Table-per-class: tabelle complete per ogni figlio

Page 33: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

33

Ereditarietà: single table● Single table prevede una singola tabella per i

padri e per i figli● Una singola tabella contiene più

specializzazioni di una stessa entità base: gli attributi di un figlio non avranno senso nel caso di un “fratello” (e saranno quindi NULL)

● La strategia single table si usa annotando la classe padre con● @Inheritance(strategy= SINGLE_TABLE)

Page 34: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

34

Ereditarietà: single table● Quando si usa una singola tabella per tutta la

gerarchia, bisogna specificare una “colonna discriminante” che contiene informazioni sul tipo dell'oggetto

● Si aggiunge @DiscriminatorColumn nelle annotazioni della classe padre● @Entity● @DiscriminatorColumn(name=”tipologia”)● public class Padre {...}

Page 35: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

35

Ereditarietà: single table● Per default Hibernate, come discriminante,

crea/cerca una colonna chiamata DTYPE di tipo stringa

● Questo default può essere sovrascritto:● discriminatorType: può essere

– DiscriminatorType.STRING– DiscriminatorType.CHAR– DiscriminatorType.INTEGER

● lenght: la lunghezza del campo, usata solo nel caso stringa

Page 36: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

36

Ereditarietà: single table● I valori contenuti nella colonna discriminante

sono, per default, i nomi delle classi figlio● Volendo usare valori differenti si dovranno

annotare le classi figlio con @DiscriminatorValue(“valore”)

Page 37: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

37

Ereditarietà: Joined● Le annotazioni sono identiche al caso Single

Table● C'è @DiscriminatorColumn,

@DiscriminatorValue eccetera● Si attua annotando la classe padre con

● @Inheritance(strategy = JOINED)● A basso livello Hibernate creerà/cercherà una

tabella per il padre...● ...e una tabella per ogni figlio, che conterrà

soltanto gli attributi che non sono già presenti nel padre

Page 38: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

38

Ereditarietà: Table Per Class● Con questa strategia, tutti gli oggetti (padre e

figli), se concreti, avranno tabelle che contengono tutti i loro attributi

● Basta annotare la classe padre con● @Inheritance(strategy = TABLE_PER_CLASS)

Page 39: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

39

Ereditarietà: Quale Strategia?● Usando Joined si avrà uno schema più

mantenibile, perchè ogni modifica di un figlio impatta solo sulla tabella del figlio, e ogni modifica al padre impatta solo sulla tabella padre

● Usando table-per-class, ogni modifica al padre impatterà anche su tutte le tabelle dei figli – mentre le performance sono migliori del caso Joined, perché non ci sono join

● Single Table ha migliori performance, perché tutte le query vengono fatte su una sola tabella, ma può diventare disordinata

Page 40: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

40

Mapped Superclass● Un caso speciale di ereditarietà si ha quando

la classe padre non è resa persistente e quindi, in teoria, non dovrebbe possedere annotazioni Hibernate

● In realtà per far funzionare l'ereditarietà dovremo annotare la classe padre come se fosse persistente, e poi aggiungere● @MappedSuperClass

● Subito dopo @Entity, per specificare che la classe padre è solo mappata e non deve essere resa persistente

Page 41: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

41

Altre annotazioni

Page 42: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

42

Dati temporali● Le proprietà di tipo java.util.Date vengono di

default mappate su attributi di tipo TIMESTAMP● Questo comportamento può essere modificato

con l'annotazione @Temporal● @Temporal(TemporalType.DATE)● @Temporal(TemporalType.TIME)● @Temporal(TemporalType.TIMESTAMP)

Page 43: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

43

Large Objects● I Large Objects sono attributi di una tabella

che contengono oggetti molto grandi: ● stringhe estese (LONGTEXT)● sequenze di byte (BLOB, Binary Large OBject)

● Per specificare che una certa proprietà va salvata in un attributo di tipo large, basta annotarla con @Lob● @Lob● public String getTitle() { … }

● Si creerà un attributo che non sarà varchar

Page 44: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

44

Generare Indici● Questa è una annotazione non inclusa in JPA,

solo in Hibernate● Gli indici possono essere applicati:

● Alla singola colonna, con l'annotazione– @Index(name=”nomedellindice”)

● Su diverse colonne contemponaneamente, annotando la classe con:

@Table(appliesTo=”nometabella”, indexes = {@Index(name=”nomeindice1”, columnNames={“col1”, “col2”}

})

Page 45: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

45

Named Query● Una Named Query è una query (in HQL) a cui

diamo un nome, per poter essere richiamata successivamente

● È composta quindi da una coppia (nome, espressione)

● Si definisce con annotazione di classe:

@Entity

@NamedQuery(name=”findAllStudents”,

query=”from Students”)

public class Student{ … }

Page 46: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

46

Named Query● La caratteristica delle Named Query è quella

di essere riutilizzabili● Se vogliamo riutilizzarle tra più classi,

dobbiamo definirle a livello di package● Si crea un file chiamato package-info.java che

conterrà le annotazioni che devono essere condivise tra tutte le classi del package

@NamedQuery(name=”findAllStudents”,

query=”from Students”)

package it.unirc.pja.example2

Page 47: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

47

Hibernate Console

Page 48: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

48

Hibernate Console● La Hibernate Console è un tool che fa parte

del plugin per Eclipse● Permette di svolgere le seguenti funzioni

● Visualizzazione rapida dei mapping e degli schemi● Scrittura di query di test HQL (parametrizzate e

non)● Generazione dello schema del database a partire

dai mapping● Generazione di diagrammi che rappresentano i

mapping

Page 49: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

49

Hibernate console: esempio● Vedi

Page 50: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

50

Metodi base di Session

Page 51: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

51

Metodi base di Session● Abbiamo già visto che l'oggetto Session è

fondamentale● Svolge la funzione di interfaccia tra i nostri

oggetti Java e Hibernate● Session ha un certo numero di metodi utilizzati

per richiamare le funzionalità di Hibernate

Page 52: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

52

Salvataggio● Quando si crea un nuovo oggetto che possiede

mapping Hibernate, questo non viene automaticamente reso persistente

● Si deve salvare per la prima volta in una Session, tramite il metodo save()● session.save(oggetto);

Page 53: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

53

Nota Bene: Confronto● Un certo oggetto reso persistente avrà due modi per

essere identificato:

● Identificativo di istanza della classe (che rappresenta l'oggetto)

● Chiave primaria (che rappresenta la tupla)● Nell'ambito di una stessa sessione entrambi gli

identificativi potranno essere usati, mentre su più sessioni l'identificativo di istanza potrebbe cambiare

● Bisogna quindi evitare di usare l'operatore == (che confronta l'identificativo di istanza); meglio usare equals(), magari implementata da noi con il confronto tra le primary key

Page 54: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

54

Caricamento● Il caricamento di oggetti persistenti avviene

tramite load()● Ha due parametri:

● La classe della entity, passata come nome (String) o come oggetto Class

● L'id dell'oggetto (chiave primaria)● Se la chiave specificata non esiste verrà

lanciata una eccezione● Simile a load() è get(): se la chiave non esiste

restituisce NULL invece di una eccezione

Page 55: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

55

Caricamento: Lock modes● Sia load() che get() supportano un terzo

parametro, opzionale, che serve a specificare il lock degli oggetti caricati

● Il lock è usato per evitare problemi di aggiornamento concorrente

● I lock vengono rilasciati alla fine della transazione

● Attenzione: usare i lock può creare problemi di deadlock, se più thread in contemporanea acquisiscono parte delle risorse e non le rilasciano (vedi Problema dei 5 filosofi)

Page 56: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

56

Caricamento: Lock modes● Lock mode disponibili:

● NONE: default; legge dal database solo se l'oggetto richiesto non è in cache

● READ: legge semre l'oggetto dal database● UPGRADE: se supportato dal database/dialect,

imposta un lock di aggiornamento; se non è possibile ottenerlo, attende che vengano rilasciati i lock che ostacolano

● UPGRADE_NOWAIT: come UPGRADE, ma se non è possibile ottenere il lock lancia subito una eccezione

Page 57: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

57

Aggiornamento dal DB● Se vogliamo ottenere l'ultima versione

dell'oggetto dal database (eliminando le modifiche fatte da noi) basta utilizzare il metodo refresh()

● In realtà Hibernate nella maggior parte dei casi lo fa in automatico, non c'è bisogno di chiamare refresh() direttamente● Il caso particolare si ha quando l'oggetto viene

aggiornato da applicazioni esterne oppure da query SQL: in questo caso Hibernate non può sapere che l'oggetto è stato aggiornato

Page 58: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

58

Update● Se un oggetto è persistente, ogni modifica che

operiamo su di esso viene “accodata” ed eseguita da Hibernate alla fine della sessione

● Non è necessario eseguire esplicitamente una operazione di update (con il metodo update())

● Nel caso volessimo salvare tutte le operazioni effettuate sul db prima del termine della sessione, possiamo usare il metodo flush()

Page 59: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

59

Update: flush() modes● La strategia di flushing “automatica” prevede

di salvare ogni oggetto prima di eseguire una query che restituisce l'oggetto stesso

● Esistono altre strategie, impostabili con setFlushMode():● ALWAYS: prima di ogni query effettua flush(),

salvando tutti gli oggetti. Lento● COMMIT: esegue flush() solo in fase di commit● MANUAL: non esegue mai flush(), dobbiamo

richiamarlo esplicitamente nel codice

Page 60: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

60

Delete● Se si deve cancellare un oggetto persistente si

può usare il metodo delete()● Il parametro di delete() è un Object, che può

essere:● L'oggetto da cancellare● Un oggetto dello stesso tipo di quello da

cancellare, con la proprietà chiave impostata (questo si usa se non abbiamo l'oggetto completo ma conosciamo solo l'id)

Page 61: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

61

SaveOrUpdate()● Il metodo save() rende persistente un oggetto

(INSERT) mentre update() lo aggiorna (UPDATE)● La prima volta va usato save(), le successive

update()● Se la prima volta si usa update(), o nelle

successive save(), ci sarà un errore● Se non sappiamo se usare save() o update(),

possiamo usare saveOrUpdate() che effettua una select per vedere se l'oggetto esiste, e poi chiama save() o update()

Page 62: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

62

Disassociazione● Può capitare di aver bisogno che un certo

oggetto non sia più persistente● Dato che ogni modifica dentro una sessione

viene tracciata da Hibernate, per poi eseguire gli aggiornamenti, vorremmo evitare che venissero tracciate operazioni che non vanno riportate sul database

● In questo caso si usa il metodo evict(), che disassocia un oggetto dalla sessione corrente

Page 63: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

63

Hibernate Query Language

Page 64: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

64

Sintassi base● Hibernate fornise un proprio linguaggio di

query, basato suglio oggetti e modellato in modo molto simile a SQL

● Poiché dall'interno di Hibernate si possono sfruttare le informazioni di mapping, molte delle query in HQL sono più compatte delle corrispondenti versioni SQL

● Ovviamente, HQL viene tradotto in SQL prima di essere inviato al database

Page 65: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

65

Sintassi base● SELECT● È identico all'equivalente SQL, solo che la

parte di proiezione (SELECT nome, cognome) è opzionale: se non si specifica si assume “SELECT *”

● La clausola FROM è seguita dal nome di una classe, piuttosto che di una tabella

Page 66: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

66

CreateQuery● Un oggetto di tipo Query può essere ottenuto,

a partire dalla corrispondente stringa HQL, tramite il metodo createQuery() di Session● Query q = session.createQuery(“from User”);

Page 67: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

67

Controllare codice SQL generato● Il codice HQL viene convertito in SQL prima di

essere inviato al database● Può capitare che, in alcuni casi, la traduzione

sia una query SQL inefficiente● Possiamo visualizzare le traduzioni tramite:

● Hibernate console in Eclipse● File di Log, se abilitiamo la proprietà “show_sql”

nel file di configurazione di Hibernate

Page 68: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

68

Filtri condizionali● Ovvero la clausola WHERE● Possiamo usare tutti gli operatori tipici di SQL

(OR, AND, =, <>, like eccetera)● In più possiamo definire dei parametri, per

realizzare query parametriche● I parametri si inseriscono come :nomeparametro● Es: “From User where name=:name”

Page 69: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

69

Named Parameters● I Named Parameters ci aiutano a difendere la

nostra applicazione dagli attacchi di SQL Injection

● Infatti la sostituzione tra parametri e valore effettivo avviene controllando il tipo esatto dell'oggetto passato● Es.

– Query query = session.createQuery(“from User where address=:address”);

– query.setEntity(“address”, myAddress);

Page 70: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

70

Pagination● Normalmente in una web application

restituiremo solo un certo numero di dati all'utente

● Se sono molti, questo significa mostrare una pagina alla volta

● L'oggetto query possiede due metodi per supportare questa funzionalità:● setFirstResult(int) : indica la tupla di partenza● setMaxResults(int) : indica quante tuple prelevare

Page 71: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

Risultato unico

● L'oggetto Query ha un metodo list() che restituisce tutti i risultati di una query

● Possiede anche un metodo uniqueResult() che restituisce solo un oggetto

● Se l'oggetto è più di uno, lancia una eccezione● Quando vogliamo ottenere solo il primo

risultato, dovremo usare una combinazione di uniqueResult() e setMaxResults(1)

Page 72: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

Order by

● HQL supporta la clausola Order By che viene usata come in SQL

● “order by nomeproprietà [desc|asc]”● Se vogliamo ordinare per più proprietà, basta

separarle con la virgola

Page 73: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

Join

● Tramite le join si possono usare più classi in una sola query

● Hibernate supporta più tipi di join:● Inner, cross, left outer, right outer, full outer

● Se ci sono i mapping non c'è bisogno di specificare le condizioni di join

Page 74: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

Aggregazioni

● HQL supporta gli operatori di aggregazione:● avg(name)● count(name|*)● max(name)● min(name)● sum(name)

Page 75: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

Aggiornamenti in blocco

● Quando serve aggiornare o cancellare un certo numero di oggetti contemporaneamente, usare un ciclo for potrebbe essere inefficiente

● Si possono usare gli equivalenti HQL di UPDATE e DELETE

● Basta creare una query di update/delete, e poi chiamarne il metodo executeUpdate()

Page 76: Programmazione Java Avanzata - unirc.it · Programmazione Java Avanzata Hibernate (Parte 2) Ing. Giuseppe D'Aqu

SQL Nativo

● L'uso di SQL nativo si dovrebbe evitare per ottenere la massima portabilità; se proprio è necessario, possiamo creare una query in SQL utilizzando il metodo● Session.createSQLQuery(String)