1. 1
Universit degli Studi dellAquila
Master in Web Technology
TECNICHE DI PERSISTENZA
A.A. 2013/14
Docente: Francesco Pititto
Studente Matricola Email
Silvio DOrazio 234422 silvio.dorazio@gmail.com
Alessandra Ponis 234457 alessadra.ponis@gmail.com
2. 2
Indice
1. Strategy ................................................................................................................................. 3
Panoramica dellapplicazione......................................................................................... 3
2. Scope ..................................................................................................................................... 3
2.1 Presentazione degli attori ..................................................................................... 3
2.2 Requisiti................................................................................................................. 4
2.2.1 Requisiti funzionali..................................................................................... 4
2.2.2 Requisiti non funzionali.............................................................................. 5
2.3 Use case diagram .................................................................................................. 6
3. La persistenza dati................................................................................................................. 7
3.1 Class diagram........................................................................................................ 7
3.2 Il framework di persistenza .................................................................................. 9
3.2.1 I mapping delle classi ................................................................................. 9
4. Larchitettura del sistema.................................................................................................... 17
3. 3
1. Strategy
Panoramica dellapplicazione
Fare la spesa 竪 unattivit che coinvolge, volente o dolente, tutte le famiglie. Spesso non basta
compiere questattivit una volta a settimana, bens狸, 竪 abitudine andarci spesso. Essendo un
mercato molto importante, soprattutto in una realt come quella italiana dove la cultura del
buon cibo 竪 sentita, diversi studiosi di marketing hanno elaborato e tuttora elaborano piani
strategici affinch辿 lutente sia invogliato e agevolato durante le fasi della spesa come la ricerca,
lacquisto e la fidelizzazione. La nostra idea nasce dalla consapevolezza che le nuove tecnologie
sono sempre pi湛 rivolte allutente e sempre pi湛 sono presenti ed utilizzate nel quotidiano di
tanti italiani, infatti il WEB con le-commerce ha aperto un mercato nuovo pieno di
potenzialit, dove piccole realt che vi investono risultano vincenti. FastMarket rispecchia la
nostra visione futura del fare la spesa nel supermercato di fiducia della zona di residenza. pi湛
di un classico e-commerce, in quanto ogni funzionalit 竪 studiata appositamente per lutente.
Grazie allausilio di questa applicazione si potr comodamente fare la spesa nei ritagli di tempo
attraverso un pc o un tablet, facendosi recapitare il tutto comodamente a casa o ritirandola in
un momento successivo. Ma soprattutto si potr godere di diversi benefici come una lista della
spesa che non si perder come i foglietti volanti, un ricettario e la possibilit di acquistare un
pasto o un panino per poi andarlo a prelevare nel punto vendita senza la fila dellora di punta.
2. Scope
2.1 Presentazione degli attori
Gli attori che interagiscono attivamente con il sistema sono:
User;
Registered user;
Employee: un attore astratto che rappresenta concettualmente qualsiasi dipendente
del supermercato, creato per rappresentare le funzionalit a cui tutti i dipendenti
possono accedere.
I dipendenti del supermercato, che possono usufruire totalmente o parzialmente delle
funzionalit di backoffice, sono stati divisi per ruolo:
a. Site admin: lutente amministratore del sito 竪 in grado di accedere a tutte le
funzionalit del backoffice, ovvero le funzionalit a cui possono accedere
anche gli altri dipendenti del supermercato pi湛 la gestione dei dipendenti del
supermercato e degli utenti registrati al sito;
b. Sales manager: dipendente incaricato della gestione degli ordini (ovvero sia le
consegne a domicilio che le prenotazioni), della gestione degli articoli e delle e-
mail per assistenza tecnica e servizio clienti.
4. 4
c. Web-marketing manager: dipendente incaricato di gestire le newsletter, le e-
mail promozionali, le informazioni del sito e la sezione ricette.
2.2 Requisiti
2.2.1 Requisiti funzionali
Di seguito presentiamo lelenco delle funzionalit implementate nellapplicazione suddivise per
attore:
Gli utenti del sito:
User:
Il sistema consentir allutente di effettuare la registrazione, inserendo tutte le
informazioni personali, creando quindi un proprio profilo.
Il sistema permetter la ricerca degli articoli del supermarket:
- per categoria (latte, detersivi o quantaltro);
- per tipologia dintolleranza (celiachia, nefropatia o quantaltro);
- per marca (Barilla, Dixan o quantaltro);
Il sistema permetter di visualizzare per ogni articolo le rispettive
caratteristiche e descrizione.
Registered user:
Allutente registrato, dopo aver effettuato lautenticazione, sar possibile
modificare il proprio profilo dal sistema.
Gli utenti amministratori del backoffice (i dipendenti):
Sales manager:
Lutente con il ruolo di Responsabile vendite gestir linserimento, la
cancellazione e la modifica degli articoli del supermercato.
Web-marketing manager:
Lutente con il ruolo Responsabile vendite sar addetto alla gestione delle
informazioni presenti allinterno del sito.
Site admin:
Oltre a fare tutto ci嘆 che fanno gli altri utenti amministratori del backoffice:
5. 5
Lutente con il ruolo di Amministratore del sito sar incaricato di gestire i
dipendenti del negozio (sar lunico in grado di aggiungere o eliminare i profili dei
dipendenti).
Tale dipendente sar anche incaricato di gestire gli utenti registrati e di avere
accesso ai loro dati in caso di problemi con i pagamenti o le prenotazioni.
Inoltre:
Ciascun dipendente sar in grado di autenticarsi e modificare il proprio profilo
dal sistema;
2.2.2. Requisiti non funzionali
Usabilit:
Il funzionamento del sistema risulter semplice da imparare affinch辿 i nuovi
utenti lo possano utilizzare immediatamente e facile da ricordare per quelli abituali. Gli
utenti non avranno n辿 voglia n辿 tempo di aspettare lunghe elaborazioni, per questo
risulter efficiente e facilmente navigabile tramite qualsiasi dispositivo.
Affidabilit:
il servizio di pagamento on-line verr delegato ad un sistema esterno sicuro ed
affidabile (Paypal) dal quale dipender il corretto funzionamento del servizio stesso;
Per gestire eventuali malfunzionamenti non pervenuti allamministratore o
particolari condizioni di stress, il sistema prevedr una funzionalit di gestione delle e-
mail per assistenza tecnica affidata ad un addetto Responsabile vendite che
permetter al medesimo di accogliere eventuali segnalazioni di errore da parte degli
utenti.
Performance:
Larchitettura di sistema permetter a molteplici utenti di usufruire
contemporaneamente dei servizi offerti e sar in grado di processare varie transazioni
nello stesso momento e di restituire loutput in tempi brevi.
Supportabilit (Manutenibilit):
Il catalogo online verr costantemente aggiornato da un responsabile vendite
per rispecchiare le disponibilit del negozio.
Il sistema verr costantemente manutenuto da un amministratore che far
periodicamente dei test per assicurarne il corretto funzionamento su qualsiasi
tecnologia e piattaforma software di ultima generazione.
Scalabilit:
Il sistema 竪 stato progettato per essere facilmente estendibile a livello di
funzionalit e di componenti software.
Vincoli
I permessi di accesso ai dati degli utenti saranno forniti soltanto allamministratore del
sistema.
6. 6
2.2 Use case diagram
Lo use case diagram di seguito riporta graficamente i requisiti funzionali del sistema
precedentemente descritti.
7. 7
3. La persistenza dati
3.1 Class diagram
Il class diagram di FastMarket definisce il modello di dominio dellapplicazione ed 竪 composto
in totale da 18 classi, ciascuna delle quali 竪 relazionata con altre classi in base ad un particolare
tipo di associazione.
In ordine alfabetico, il sistema 竪 composto dalle seguenti classi:
Address: rappresenta lindirizzo che pu嘆 essere associato al profilo di un particolare
utente ed 竪 di fondamentale importanza quando un utente registrato si trova in
fase di pagamento. Ad ogni utente possono essere associati pi湛 indirizzi.
Booking: classe che estende da Order creata per rappresentare il concetto di
prenotazione della spesa o del pasto pronto che un utente registrato pu嘆 effettuare
tramite il sito per poi ritirare i prodotti nel punto vendita. Ogni utente registrato
pu嘆 effettuare pi湛 prenotazioni.
Brand: ad ogni prodotto, alimentare e non, viene associata una marca particolare
che 竪 rappresentata allinterno dellapplicazione tramite questa classe; ogni marca
pu嘆 essere associata a pi湛 prodotti. Tale classe viene utilizzata allinterno della
pagina Catalogo prodotti, accessibile dal front-end, come filtro di ricerca
avanzata.
Cart: classe che rappresenta il carrello persistente (dunque non in sessione, dato
che il carrello in sessione viene allocato solo per gli utenti non registrati) che viene
associato ad un utente registrato. Ogni utente pu嘆 gestire un carrello al massimo.
CartLine: classe che rappresenta il prodotto inserito nel carrello. Ad ogni carrello
possono essere associate pi湛 istanze di CartLine.
Category: ad ogni prodotto, oltre alla marca, viene associata una categoria che
rispecchia le stesse tipologie di prodotti presenti allinterno degli scaffali del
supermercato ed 竪 rappresentata da questa classe. Anche Category viene utilizzata
come filtro di ricerca avanzata nella pagina Catalogo prodotti.
Delivery: classe che estende da Order e rappresenta il concetto di consegna a
domicilio; essa viene creata dopo che lutente ha inserito lindirizzo dove preferisce
ricevere la spesa per poi scegliere se pagare on-line o presso la sede del
supermercato. Ogni utente pu嘆 richiedere al sistema di effettuare pi湛 consegne.
District: rappresenta il comune di residenza che lutente deve selezionare quando
inserisce un nuovo indirizzo nel sistema. Tale classe 竪 molto importante per il
servizio di consegna a domicilio poich辿 tramite la stessa il sistema 竪 in grado di
determinare se il camioncino delle consegne del supermercato effettua il servizio
anche verso il comune selezionato o meno.
Grocery: classe che rappresenta il prodotto alimentare. Grocery estende da Product
e ne aggiunge degli attributi propri.
IntoleranceCategory: dato che lapplicazione web, a differenza degli altri siti e-
commerce presenti nel mercato, offre lopportunit di acquistare dei prodotti per
intolleranti, tale classe rappresenta la categoria di intolleranza da eventualmente
8. 8
associare ad alcuni prodotti alimentari presenti nel sistema.
Anche IntoleranceCategory pu嘆 essere selezionata dallutente per effettuare una
ricerca avanzata nella pagina Catalogo prodotti.
NonGrocery: classe che rappresenta il prodotto non alimentare. Allo stesso modo di
Grocery, anche questa classe estende da Product e presenta degli attributi propri.
Order: rappresenta il concetto di ordine che pu嘆 essere effettuato al sistema
dallutente in fase di acquisto. E una classe padre dalla quale estendono Booking e
Delivery e serve per raggruppare gli attributi che hanno in comune i due concetti di
prenotazione in negozio e consegna a domicilio.
Product: classe padre che rappresenta il generico concetto di prodotto messo in
vendita dal nostro e-commerce. Da tale classe estendono Grocery e NonGrocery ed
竪 stata creata per raggruppare gli attributi che tali classi hanno in comune.
Province: classe che rappresenta la provincia che deve essere necessariamente
associata al comune, che viene poi selezionato quando viene inserito un nuovo
indirizzo allinterno del sistema.
Region: classe che rappresenta la regione che deve essere necessariamente
associata alla provincia che viene a sua volta associata ad un comune particolare.
Role: classe che rappresenta il ruolo da attribuire obbligatoriamente allutente una
volta che lo stesso viene inserito allinterno del sistema.
Ad ogni utente possono essere associati pi湛 ruoli e ci嘆 竪 stato fatto pensando agli
amministratori del back-end (i dipendenti) che, a seconda del ruolo a cui viene loro
dato, possono accedere a diverse funzionalit dellapplicazione.
SystemInformation: classe che rappresenta i dati che vengono inseriti dai
dipendenti incaricati allinterno del sistema. Si tratta di politiche sulla privacy o altre
informazioni sul funzionamento del servizio che gli utenti possono visualizzare
tramite interfaccia e sono dettati dal supermercato di riferimento.
User: tale classe rappresenta gli utenti del sito che si dividono in due
macrocategorie: utenti registrati e dipendenti. Ad ogni generico utente registrato
possono essere potenzialmente associati uno o pi湛 ruoli.
9. 9
3.2 Il framework di persistenza
Abbiamo curato laspetto della persistenza dati facendo uso del framework opensource
Hibernate il quale ci ha permesso, attraverso luso dei mapping xml object/relational, di
rendere persistenti in modo automatizzato gli oggetti creati nellapplicazione web allinterno di
tabelle relazionali.
3.2.1 I mapping delle classi
Ogni POJO presente nellapplicazione descrive una classe che compone il modello di business.
Ogni classe entity 竪 un firt-class business object che ha un proprio ciclo di vita, che allinterno
del database relazionale ha una sua identit e che esiste indipendentemente da qualsiasi altra
classe entity del sistema.
Per ciascun POJO presente nellapplicazione web 竪 stato generato automaticamente un
mapping hbm xml con allinterno specificati una serie di metadati che Hibernate 竪 in grado di
comprendere a runtime.
Di seguito presenteremo le opzioni che abbiamo scelto di inserire allinterno dei mapping e le
scelte fatte per mappare le classi e le propriet allinterno rispettivamente delle tabelle e delle
colonne nel DB.
La Entity Address
Abbiamo scelto di creare il mapping di Address inserendo, come per tutte le altre classi del
sistema, le propriet della classe allinterno del tag <property> con attributi:
Lazy=false perch辿 altrimenti per fare il lazy loading delle propriet Hibernate
necessiterebbe di una bytecode instrumentation (tuttavia, questa regola non si
applica a tutti i tipi);
Access=field per far s狸 che Hibernate acceda a runtime al campo con lo stesso
nome.
Not-null=true applicato soltanto ad alcune colonne del DB, per far s狸 che
Hibernate segnali propriet a cui vengono illegalmente assegnati valori nulli.
Invece, il <generator> scelto per creare nuove PK allinterno della tabella ADDRESSES, come
per il resto delle Entity, 竪 di tipo sequence. Esso consente di creare nuovi identificativi
tramite una o pi湛 sequenze, che possono essere di tipo long, short o int. Nel caso della nostra
applicazione, abbiamo deciso di far creare ad Hibernate una sequenza per ogni Entity
assegnando a ciascuna un nome particolare.
<hibernate-mapping>
<class name="it.univaq.mwt.fastmarket.business.model.Address" table="ADDRESSES">
<id name="id" type="long">
<column name="ID" />
<generator class="sequence">
<param name="sequence">SEQUENCE_ADDRESSES</param>
10. 10
</generator>
</id>
<property access="field" lazy="false" name="street" type="java.lang.String">
<column name="STREET" not-null="true" />
</property>
<property access="field" lazy="false" name="streetNumber" type="int">
<column name="STREETNUMBER" not-null="true" />
</property>
<property access="field" lazy="false" name="country" type="java.lang.String">
<column name="COUNTRY" not-null="true" />
</property>
<property access="field" lazy="false" name="zipCode" type="int">
<column name="ZIPCODE" not-null="true" />
</property>
<many-to-one name="district"
class="it.univaq.mwt.fastmarket.business.model.District" access="field" fetch="join">
<column name="DISTRICT_ID" not-null="true" />
</many-to-one>
<many-to-one name="user" class="it.univaq.mwt.fastmarket.business.model.User"
access="field" fetch="join">
<column name="USER_ID" not-null="true" />
</many-to-one>
</class>
</hibernate-mapping>
Come 竪 possibile notare, allinterno del mapping sono specificate due associazioni di tipo
<many-to-one> verso le classi District e User. Ci嘆 significa che nella tabella ADDRESSES viene
riservata una colonna per le rispettive FK verso le tabelle DISTRICTS e USERS.
Abbiamo scelto questo tipo di associazione perch辿 ci aspettiamo che svariati indirizzi possano
essere associati ad uno stesso comune e che un utente possa avere diversi indirizzi, uno dei
quali pu嘆 essere selezionato durante la fase di pagamento per indicare al dipendente dove
preferisce ricevere la spesa.
Per quanto riguarda gli attributi dellassociazione, abbiamo inserito:
Access=field per consentire laccesso diretto al campo per ogni propriet
specificata.
Fetch=join che disabilita il lazy load e carica oltre allentit padre lintera
collezione referenziata.
Le Entity District, Province e SystemInformation
Esistono vari casi in cui una Entity del sistema presenta un mapping analogo a quello descritto
in precedenza, con una o pi湛 associazioni di tipo <many-to-one>, ciascuna scelta in base ad un
criterio ben preciso:
La Entity District con la Entity Province di modo da poter associare diversi comuni
ad ogni provincia;
La Entity Province con la Entity Region di modo da poter associare diverse province
ad una sola regione;
La Entity SystemInformation con la Entity User di modo da poter associare diversi
dati riguardanti il sistema ad un solo utente autore;
11. 11
Le Entity Cart e CarLine
Stabilire il tipo di associazione tra la classe Cart e CartLine 竪 stato tuttaltro che semplice.
Abbiamo scelto di optare, infine, per unassociazione <many-to-one> allinterno del mapping di
CartLine in cui la FK allinterno della tabella di CartLine fa riferimento alla PK della tabella di
Cart.
<hibernate-mapping>
<class name="it.univaq.mwt.fastmarket.business.model.Cart" table="CARTS">
<id name="id" type="long">
<column name="ID" />
<generator class="sequence">
<param name="sequence">SEQUENCE_CARTS</param>
</generator>
</id>
<property access="field" lazy="false" name="name" type="java.lang.String">
<column name="NAME" not-null="true" />
</property>
<property access="field" lazy="false" name="totalPrice" type="float">
<column name="TOTALPRICE" />
</property>
<many-to-one name="user" class="it.univaq.mwt.fastmarket.business.model.User"
access="field" fetch="join">
<column name="USER_ID" unique="true" not-null="true" />
</many-to-one>
</class>
</hibernate-mapping>
<hibernate-mapping>
<class name="it.univaq.mwt.fastmarket.business.model.CartLine" table="CARTLINES">
<id name="id" type="long">
<column name="ID" />
<generator class="sequence">
<param name="sequence">SEQUENCE_CARTLINES</param>
</generator>
</id>
<property access="field" lazy="false" name="quantity" type="int">
<column name="QUANTITY" not-null="true" />
</property>
<many-to-one name="cart" class="it.univaq.mwt.fastmarket.business.model.Cart"
access="field" fetch="join">
<column name="CART_ID" not-null="true" />
</many-to-one>
<many-to-one name="product"
class="it.univaq.mwt.fastmarket.business.model.Product" access="field" fetch="join">
<column name="PRODUCT_ID" not-null="true" />
</many-to-one>
</class>
</hibernate-mapping>
La scelta del mapping <many-to-one> tra Cart e User serve in realt ad esprimere
unassociazione one-to-one unidirezionale per la quale allinterno della tabella CARTS viene
inserita la FK che referenzia la PK della tabella associata USERS.
Alla colonna dentro a CARTS dove viene inserita la FK verso USERS 竪 stato necessario, tuttavia,
specificare la clausola unique=true per far s狸 che Hibernate legga realmente la relazione
come one-to-one.
Invece, la scelta del mapping <many-to-one> tra CarLine e Cart 竪 dettata dal fatto che,
inserendo la FK allinterno della tabella CARTLINES, riusciamo ad assicurarci che una o pi湛
istanze di CartLine siano associate ad un solo carrello; per rafforzare tale unicit, abbiamo
anche gestito il lancio delleccezione di violazione del vincolo di chiave univoca allinterno
dellapplicazione nel caso in cui lutente cerchi di associare una stessa CartLine a pi湛 carrelli.
12. 12
In realt, essendo unapplicazione e-commerce che consente ad ogni utente di avere un solo
carrello, abbiamo pensato che lutente registrato eliminerebbe dal carrello soltanto una
cartLine per volta perci嘆 non si produrrebbe mai leventualit in cui un utente tenta di
eliminare direttamente il carrello riempito dalle cartLines (eventualit che viene, ad ogni
modo, gestita nel backend dellapp nel caso in cui un dipendente del supermercato cerchi di
farlo).
Infine, allinterno di CartLine abbiamo dichiarato un'altra associazione <many-to-one> per
creare un riferimento verso la Entity Product, dato che svariate righe del carrello possono
contenere uno stesso prodotto.
Le Entity Order, Booking e Delivery
Nel caso di Order, Booking e Delivery le Entity sono legate tramite una generalizzazione, per la
quale Booking e Delivery estendono da Order. Tra le varie strategie a disposizione per mappare
lereditariet, abbiamo scelto quello che W. Keller ha definito One Class One Table, ovvero
abbiamo mappato sia le propriet della classe astratta che le propriet delle classi concrete
creando cos狸 3 tabelle diverse; ci嘆 significa che ciascuna tabella contiene gli attributi della
rispettiva classe. In questo caso, dato che Delivery e Booking ereditano anche la chiave
primaria, il join tra le tabelle viene attuato tramite la colonna della PK allinterno della tabella
padre.
Abbiamo deciso di optare per questo mapping poich辿, tra le varie opzioni disponibili, 竪
ottimale a livello di consumo di spazio nel DB e questo aspetto 竪 per noi fondamentale dato
che nel nostro caso la classe Booking presenta svariati attributi.
A livello di mapping xml 竪 stato, dunque, generato un unico mapping per la classe padre Order
con allinterno specificati i tag <joined-subclass> con internamente presente lattributo
extends.
<hibernate-mapping>
<class abstract="true" name="it.univaq.mwt.fastmarket.business.model.Order" table="ORDERS">
<id name="id" type="long">
<column name="ID" />
<generator class="sequence">
<param name="sequence">SEQUENCE_ORDERS</param>
</generator>
</id>
<property access="field" lazy="false" name="creationDate" type="date">
<column name="CREATIONDATE" not-null="true" />
</property>
<property access="field" lazy="false" name="totalPrice" type="float">
<column name="TOTALPRICE" not-null="true" />
</property>
<many-to-one name="cart" class="it.univaq.mwt.fastmarket.business.model.Cart"
access="field" fetch="join">
<column name="CART_ID" not-null="true" />
</many-to-one>
<joined-subclass name="it.univaq.mwt.fastmarket.business.model.Booking"
extends="it.univaq.mwt.fastmarket.business.model.Order"
table="BOOKINGS">
<key>
<column name="ID" not-null="true" />
</key>
<property access="field" lazy="false" name="expirationDate" type="date">
<column name="EXPIRATIONDATE" not-null="true" />
</property>
</joined-subclass>
<joined-subclass name="it.univaq.mwt.fastmarket.business.model.Delivery"
13. 13
extends="it.univaq.mwt.fastmarket.business.model.Order"
table="DELIVERIES">
<key>
<column name="ID" not-null="true" />
</key>
<property access="field" lazy="false" name="dispatchDate" type="date">
<column name="DISPATCHDATE" not-null="true" />
</property>
<property access="field" lazy="false" name="deliveryCosts" type="float">
<column name="DELIVERYCOSTS" not-null="true" />
</property>
<property access="field" lazy="false" name="deliveryType"
type="java.lang.String">
<column name="DELIVERYTYPE" />
</property>
</joined-subclass>
</class>
</hibernate-mapping>
Le Entity Product, Grocery e NonGrocery
Un altro caso di generalizzazione mette in relazione le Entity Product, Grocery e NonGrocery. Il
mapping 竪 analogo a quello appena descritto tranne per il fatto che la classe padre ha anche
una FK verso Brand e una verso Category e la classe figlia Grocery ha una FK verso
IntoleranceCategory.
Anche in questo caso 竪 stato creato un unico mapping per la Entity Product con allinterno le
entit figlie Grocery e NonGrocery, che vengono dichiate tramite lattributo <joined-
subclass>.
<hibernate-mapping>
<class name="it.univaq.mwt.fastmarket.business.model.Product" table="PRODUCTS">
<id name="id" type="long">
<column name="ID" />
<generator class="sequence">
<param name="sequence">SEQUENCE_PRODUCTS</param>
</generator>
</id>
<property access="field" lazy="false" name="name" type="java.lang.String">
<column name="NAME" not-null="true" unique="true" />
</property>
<property access="field" lazy="false" name="description"
type="java.lang.String">
<column name="DESCRIPTION" />
</property>
<property access="field" lazy="false" name="price" type="float">
<column name="PRICE" not-null="true" />
</property>
<property access="field" lazy="false" name="stock" type="int">
<column name="STOCK" not-null="true" />
</property>
<many-to-one name="brand" class="it.univaq.mwt.fastmarket.business.model.Brand"
access="field" fetch="join">
<column name="BRAND_ID" not-null="true" />
</many-to-one>
<many-to-one name="category"
class="it.univaq.mwt.fastmarket.business.model.Category" access="field" fetch="join">
<column name="CATEGORY_ID" not-null="true" />
</many-to-one>
<property access="field" lazy="false" name="path" type="java.lang.String">
<column name="PATH" />
</property>
<joined-subclass name="it.univaq.mwt.fastmarket.business.model.Grocery"
extends="it.univaq.mwt.fastmarket.business.model.Product" table="GROCERIES">
<key>
<column name="ID" not-null="true" />
</key>
14. 14
<property access="field" lazy="false" name="expirationDate" type="date">
<column name="EXPIRATIONDATE" not-null="true" />
</property>
<property access="field" lazy="false" name="pricePerKg" type="float">
<column name="PRICEPERKG" />
</property>
<property access="field" lazy="false" name="pricePerLt" type="float">
<column name="PRICEPERLT" />
</property>
<many-to-one name="intoleranceCategory"
class="it.univaq.mwt.fastmarket.business.model.IntoleranceCategory" fetch="join">
<column name="INTOLERANCECATEGORY_ID" />
</many-to-one>
</joined-subclass>
<joined-subclass name="it.univaq.mwt.fastmarket.business.model.NonGrocery"
extends="it.univaq.mwt.fastmarket.business.model.Product" table="NONGROCERIES">
<key>
<column name="ID" not-null="true" />
</key>
<property access="field" lazy="false" name="scopeOfUse"
type="java.lang.String">
<column name="SCOPEOFUSE" />
</property>
</joined-subclass>
</class>
</hibernate-mapping>
Le Entity User e Role
Nel caso di User e Role, abbiamo deciso di definire una relazione bidirezionale che permette di
navigare verso entrambi i lati dellassociazione.
In questo modo, ci 竪 possibile ottenere con facilit sia tutti gli utenti a cui sono stati associati
uno o pi湛 ruoli che tutti i ruoli che sono stati associati ad uno o pi湛 utenti.
A livello di mapping, le due classi entity vengono messe in relazione dichiarando una collezione
di oggetti sia allinterno del mapping di User che in quello di Role.
<hibernate-mapping>
<class name="it.univaq.mwt.fastmarket.business.model.User" table="USERS">
<id name="id" type="long">
<column name="ID" />
<generator class="sequence">
<param name="sequence">SEQUENCE_USERS</param>
</generator>
</id>
<property access="field" lazy="false" name="username" type="java.lang.String">
<column name="USERNAME" not-null="true" unique="true" />
</property>
<property access="field" lazy="false" name="password" type="java.lang.String">
<column name="PASSWORD" not-null="true" />
</property>
<property access="field" lazy="false" name="firstName" type="java.lang.String">
<column name="FIRSTNAME" not-null="true" />
</property>
<property access="field" lazy="false" name="middleName" type="java.lang.String">
<column name="MIDDLENAME" />
</property>
<property access="field" lazy="false" name="lastName" type="java.lang.String">
<column name="LASTNAME" not-null="true" />
</property>
<property access="field" lazy="false" name="gender" type="char">
<column name="GENDER" />
</property>
<property access="field" lazy="false" name="mobilePhone"
type="java.lang.String">
<column name="MOBILEPHONE" />
</property>
<property access="field" lazy="false" name="telephone" type="java.lang.String">
<column name="TELEPHONE" />
</property>
15. 15
<property access="field" lazy="false" name="email" type="java.lang.String">
<column name="EMAIL" not-null="true" />
</property>
<set name="roles" table="USERS_ROLES" inverse="false" access="field"
lazy="true">
<key>
<column name="USER_ID" not-null="true" />
</key>
<many-to-many class="it.univaq.mwt.fastmarket.business.model.Role"
column="ROLE_ID" />
</set>
</class>
</hibernate-mapping>
<hibernate-mapping>
<class name="it.univaq.mwt.fastmarket.business.model.Role" table="ROLES">
<id name="id" type="long">
<column name="ID" />
<generator class="sequence">
<param name="sequence">SEQUENCE_ROLES</param>
</generator>
</id>
<property access="field" lazy="false" name="name" type="java.lang.String">
<column name="NAME" not-null="true" />
</property>
<property access="field" lazy="false" name="description" type="text">
<column name="DESCRIPTION" />
</property>
<set name="users" table="USERS_ROLES" cascade="save-update" inverse="true"
access="field" lazy="true">
<key>
<column name="ROLE_ID" />
</key>
<many-to-many class="it.univaq.mwt.fastmarket.business.model.User" column="USER_ID"
/>
</set>
</class>
</hibernate-mapping>
Analizzando il mapping di User, notiamo che alla property username 竪 specificato lattributo
unique=true. Esso 竪 stato applicato anche ad altre propriet presenti in altri mapping (es.
alla propriet name di Brand) e permette di generare istruzioni DDL di vincolo di unicit alla
colonna corrispondente nel DB.
Per quanto riguarda, invece, le collezioni di oggetti presenti allinterno di entrambi i mapping
User e Role:
abbiamo scelto di dichiarare un set di oggetti poich辿 corrisponde allinterfaccia
java.util.Set e ci siamo resi conto che fa al caso nostro poich辿, oltre a preservare
lordine degli oggetti, non ammette duplicati;
abbiamo inserito lattributo cascade=save-update cosicch辿 Hibernate navighi
lassociazione ogniqualvolta un oggetto viene salvato o modificato e renda
persistenti le istanze transienti o le modifiche apportate alle istanze fuori dal
contesto transazionale;
abbiamo dichiarato lattributo inverse=true allinterno del set users dentro al
mapping di Role per informare Hibernate quale lato dellassociazione non deve
sincronizzare con il DB.
In questo caso viene istruito Hibernate di ignorare qualsiasi cambiamento
apportato alla collezione users e, al contrario, di sincronizzare con il database
16. 16
soltanto la collezione roles tramite la tabella associativa. Facendo ci嘆, evitiamo di
eseguire due volte lo stesso statement SQL sulla stessa FK.
Abbiamo optato per linserimento di lazy=true che 竪 in realt la strategia di
default, di modo da non richiedere ad Hibernate di caricare dal database oltre
allistanza della Entity anche la collezione di oggetti associati.
17. 17
4. Larchitettura del sistema
Per realizzare lapplicazione FastMarket, abbiamo optato per unarchitettura J2EE nella quale i
vari componenti architetturali si trovano sulla stessa JVM ed interagiscono tra loro a livello
locale al fine di far funzionare lintero sistema.
Pi湛 precisamente, abbiamo un modello architetturale nel quale vi 竪 da un lato un client web
component locale che gestisce la parte di presentazione, da un altro i componenti lato server
che implementano lintera logica di business e da un altro ancora un EIS (Enterprise
Information System) che fornisce i dati, che in questo caso 竪 un DB Oracle.
Il web component che si occupa sia della lookup JNDI verso linterfaccia locale degli EJB che
della gestione della parte web (ovvero del rendering dellinterfaccia), la logica di business
(ovvero gli EJB) e il modello di dominio vengono impacchettati allinterno di un file con
estensione .ear ed assemblati allinterno dellapplication server Glassfish.
Una volta che l.ear viene deployato ed eseguito su Glassfish il ContextLoaderListener di Spring
legge il file root-context e, in base ai parametri specificati internamente, fa una lookup JNDI
verso gli EJB che si trovano dentro allEJB container dellapplication server. La Dispatcher
Servlet si occupa invece di costruire i componenti controller per gestire le richieste http e, per
fare ci嘆, inietta allinterno degli stessi ogni interfaccia remota che trova annotata con
@Autowired.
Per essere pi湛 precisi, il client invoca uno o pi湛 metodi dellinterfaccia locale annotata con
@Local che a sua volta richiama i relativi metodi dichiarati nel session bean (EJB) stateless
ovvero che non tiene memoria della transazione svolta annotato appunto con @Stateless.
Allinterno di ciascun bean viene dichiarata la relativa interfaccia locale tramite lannotazione
@Local(NomeInterfaccia.class) mentre ogni metodo viene annotato tramite
@TransactionAttribute(TransactionAttributeType.REQUIRED) per indicare che se al client che
invoca un metodo del bean 竪 associato un determinato contesto transazionale, allora il
container richiamer il metodo del bean allinterno di tale contesto. Inoltre, lannotazione
@TransactionManagement(TransactionManagementType.CONTAINER) posta sopra alla classe
indica che tutti i metodi vengono gestiti dal container.
La gestione della persistenza dati viene, invece, delegata al framework Hibernate tramite
lutilizzo delle sessioni e dei mapping xml object/relational contenuti allinterno del modello di
dominio mentre il servizio di connessione al DB Oracle 竪 fornito dallapplication server tramite
il connettore JDBC.
Alla fine di ogni processo di elaborazione delle richieste http, lapplicazione web eseguita su
Glassfish gestisce la parte di vista da renderizzare allutente tramite la tecnologia per
implementare le view nota come JavaServer Pages. In realt, per嘆, la costruzione della vista
viene delegata al framework di templating Apache tiles il quale assembla diversi frammenti
(jsp) per costruire lintera pagina web.