Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
it EDITORIALE
DIRETTORE RESPONSABILE
MARIALETIZIA MARI
EDITORIAL BOARD
STEFANO SANNA, MICHELE SCIABARRÀ,
F A B I O S T A R O , TO N Y M O B I L Y
Sun Microsystems
COLLABORATORI
STEFANO SANNA
MICHELE SCIABARRÀ
RICCARDO SOLIMENA
FA B I O S T A R O
Con questa acquisizione, MySQL AB è a tutti gli effetti una business unit di Sun
GRUPPO EDITORIALE INFOMEDIA SRL
V I A V A L D E R A P. 1 1 6 Microsystems, e potrà avvalersi del peso di Sun per far crescere ulteriormente il
5 6 0 3 8 PO N S A C C O ( P I ) I T A L I A prodotto, in termini di marketing e di servizi.
TE L 0 5 8 7 7 3 6 4 6 0 F A X 0 5 8 7 7 3 2 2 3 2
INFORMAZIONI@GRUPPOINFOMEDIA.IT Sun, invece, oltre ad ampliare il portfolio dei propri prodotti, si posiziona giusto
W W W. I N F O M E D I A . I T
dietro la “M” dell’acronimo LAMP, una posizione decisamente centrale nel mondo
DIREZIONE del software open source.
N A T A L E FI N O E sul Nasdaq il valore del titolo Sun (il cui simbolo, guarda caso, è JAVA) giusto in
concomitanza dell’intera operazione ha avuto un rialzo.
CONTATTI
TE C H N I C A L B O O K Se da un punto di vista del licensing e di ciò che riguarda la programmazione con
(BOOK@GRUPPOINFOMEDIA.IT) MySQL non ci sono novità di sorta, ciò che verrà potenziato è il supporto tecnico, che
MARKETING & ADVERTISING Sun offre in modalità 24x7 per l’intero portfolio di prodotti MySQL.
SEGRETERIA: 0587736460
(MARKETING@GRUPPOINFOMEDIA.IT) In sintesi un robusto supporto commerciale per un prodotto software open source.
AMMINISTRAZIONE Indispensabile in ambienti con applicazioni mission-critical basate su MySQL.
(AMMINISTRAZIONE@GRUPPOINFOMEDIA.IT)
SEGRETERIA Oltre al supporto tecnico, l’acquisizione potrà far convergere più speditamente
(INFORMAZIONI@GRUPPOINFOMEDIA.IT) MySQL verso importanti tappe per applicazioni di fascia alta (dallo sviluppo di
nuovi engine, al supporto multicore spinto, all’interoperabilità, alla sincronizzazione
GRAFICA distribuita dei dati, e via dicendo).
(GRAFICA@GRUPPOINFOMEDIA.IT)
UFFICIO ABBONAMENTI Per quanto riguarda Java in particolare, ci auguriamo che la maggiore affinità
TE L 0 5 8 7 7 3 6 4 6 0 F A X 0 5 8 7 7 3 2 2 3 2 tra Sun, MySQL AB e le relative community permetta di sviluppare sempre più
ABBONAMENTI@INFOMEDIA.IT strumenti evoluti e tecnologie per poter far interagire in modo ancor più efficiente e
W W W. I N F O M E D I A . I T ottimizzato le applicazioni Java con basi di dati basate (anche) su MySQL.
JAVA E TUTTI I MARCHI DERIVATI
Con questo passo Sun (che già supporta direttamente PostgresSQL) si propone
SONO MARCHI O MARCHI REGISTRATI
DI SUN MICROSYSTEMS, INC. NEGLI sempre più come player nel mondo data center, e MySQL (con 55.000 download al
U S A E I N A L T R I PA E S I . I L G R U P P O giorno) è un’importante pedina per consolidare ulteriormente questa posizione.
EDITORIALE INFOMEDIA È INDIPEN-
DENTE DA SUN MICROSYSTEMS, INC.
La redazione di Java Journal
JAVA JOURNAL È UNA RIVISTA DEL
GRUPPO EDITORIALE INFOMEDIA SRL
DIREZIONE E AMMINISTRAZIONE:
V I A V A L D E R A P. 1 1 6 - P O N S A C C O ( P I )
R E G I S T R A Z I O N E P R E S S O I L TR I B U N A L E
DI PISA N.19/06 DEL 5/9/2006
solo
49,00
Eu ro
Se siete tra quelle persone a cui è sempre piaciuto smontare le cose per vedere come sono
fa�e, allora questo libro è per voi. Fare gli archite�, di qualsiasi campo si tra�, vuol dire
cercare di coniugare due aspe�: uno tecnico e uno crea�vo.
Quello tecnico, perché l’archite�o pensa alla stru�ura delle cose, a come sono composte
da par� più piccole e a come queste interagiscono fra loro per far muovere un corpo com-
plesso. Tu�o questo mi è sempre sembrato affascinante. L’aspe�o crea�vo è dovuto al fa�o
che un archite�o, quando è mol� anni che fa il suo lavoro, sviluppa una specie di senso
este�co di quello che fa. Vedere le cose muoversi in armonia ed evolvere è sicuramente
una grossa soddisfazione. L’importante è capire i principi fondamentali del funzionamento,
poi, i pezzi possono essere assembla� in miliardi di modi diversi e dar vita ad un numero,
ancora maggiore, di situazioni e stru�ure diverse. Lo stesso accade ad un archite�o IT.
“Architetture Enterprise”
Ordinalo su
www.shopinfomedia.com
JAVA Journal numero 5
Educational
DAO Generator
di Riccardo Solimena 23
Focus
JPA: JAVA Persistence API - Seconda parte
di Fabio Staro 38
Rubriche
Community Watch
Intervista al JAVA User Group Torino
di Stefano Sanna 46
Java Pocket Guide Core Servlets and JavaServer Value Pack: Absolute Java
Cookbook, Second Edition Pages, Volume 2 - Advanced (Int Ed) with Practical
di R. Liguori e P. Liguori Technologies 2nd Edition Debugging in Java
O’ Reilly di M. Hall, L. Brown e Y. Chaikin di W. Savitch e Ann Ford
191 pp - euro 20,95 Addison Wesley Addison Wesley
ISBN 9780596514198 736 pp - euro 44,95 Value pack - euro 83,95
ISBN 9780131482609 ISBN 9781405825054
Programming with Alice and Java Software Solutions. JavaFX Script: Dynamic
Java. International Edition Foundations of Program Java Scripting for Rich
di J. Lewis e P. DePasquale Design: International Internet/Client-side
Addison Wesley Edition (VI) Applications
360 pp - euro 75,95 di J. Lewis e W. Loftus di J. Weaver
ISBN 9780321549358 Addison Wesley Apress
832 pp - euro 74,95 216 pp - euro 38,90
ISBN 9780321549341 ISBN 9781590599457
Pro NetBeans IDE 6: Rich Client The Ruby Programming Language AJAX, RIA and Web
Platform Edition di D. Flanagan e Y. Matsumoto Development
di A. Myatt O’ Reilly di di P. Deitel e H. Deitel
Apress 444 pp - 39,00 euro Prentice Hall
491 pp - euro 55,00 ISBN 9780596516178 1040 pp - 52,95 euro
ISBN 9781590598955 ISBN 9780131587380
Garanzia di riservatezza - Il Gruppo Editoriale Infomedia garantisce la massima riservatezza dei dati da Lei forniti e la possibilità di richiederne gratuitamente la rettifica o la cancellazione scrivendo a: Responsabile Dati - Gruppo Editoriale
Infomedia Srl, V. Valdera P. 116, 56038 PONSACCO (PI). Le informazioni custodite nel nostro archivio verranno utilizzate al solo scopo di inviarle proposte commerciali, in conformità alla legge 196/03 sulla tutela dei dati personali.
Le spese di spedizione sono soggette a variazioni in base alle tariffe postali. Per i pagamenti con assegno, c/c postale e bonifico bancario consigliamo di chiedere conferma in redazione oppure consultare il sito Internet.
PER POSTA: + 3,00 Euro A MEZZO CORRIERE: + 7,00 Euro
ALLEGO ASSEGNO BANCARIO INTESTATO A “GRUPPO EDITORIALE INFOMEDIA SRL” - NON TRASFERIBILE
CONTRASSEGNO (solo per spedizione a mezzo Posta): + 8,00 Euro
ALLEGO VERSAMENTO SU C/C POSTALE N.14291561 INTESTATO A “GRUPPO EDITORIALE INFOMEDIA SRL - PONSACCO” - CODICE IBAN: IT84X0760114000000014291561 - Indicare la causale del versamento
E PAGAMENTO
SPEDIZIONE
ALLEGO FOTOCOPIA DEL BONIFICO BANCARIO SU C/C 000000014804 CAB 25200 ABI 01030 CIN “A” - MONTE DEI PASCHI DI SIENA, AGENZIA DI PERIGNANO - CODICE IBAN: IT84A0103025200000000014804
CARTA DI CREDITO VISA/MASTERCARD/CARTASI’ N. SCADENZA CODICE DI SICUREZZA “CV2”
TITOLARE _______________________________________________
NATO IL FIRMA _______________________________________________________
SI, mi voglio iscrivere gratuitamente alla newsletter Infomedia che mi tiene aggiornato sui prossimi argomenti delle mie riviste di programmazione e mi informa delle offerte, le nuove uscite e le prossime pubblicazioni. Posso
annullare la mia iscrizione in qualsiasi momento alla pagina: www.infomedia.it/newsletter.php. Questo è il mio indirizzo di posta elettronica: ______________________________________________
JAVA Journal JBOSS Seam speciale
Intervista a
Fabio Staro su
JBoss Seam
Ciao Fabio, per prima cosa una breve presenta- ticolo di approfondimento su Seam?
zione. Ci parli un attimo di te?
framework per
Seam risolve questo limite unificando i modelli a
Java Enterprise Edition componente di JSF e degli EJB 3.0 eliminando di fat-
to il codice di integrazione, il cosiddetto “glue code”,
tra le tecnologie. Tanto per essere chiari, in Seam un
action listener JSF può essere, ed anzi lo è solitamente,
un EJB di tipo session … business di tipo “long running” dove lo stato è gestito e
reso persistente da un motore di BPM (business process
management). Una business process interaction può coin-
Ma non va contro alcune delle best practice? volgere più utenti e lo stato è condiviso tra questi in un
modo ben definito.
Ha funzionalità AJAX?
Cos’è una conversation in Seam?
Sì. Seam fornisce un “built-in JavaScript remoting layer”
per invocare i componenti EJB. I client AJAX possono
Una “conversazione” in Seam è una unità di lavoro dal invocare componenti server side facilmente e senza la
punto di vista dell’utente costruita sulle diverse interazio- necessita di un action layer intermedio. Seam 1.1 integra
ni che l’utente ha con il sistema allo scopo di risolvere un soluzioni open source JSF-AJAX based come ICEfaces e
problema specifico come per esempio la prenotazione di un Ajax4JSF.
volo o la registrazione del profilo in una anagrafica. Per-
tanto una “conversazione” è costituita da varie richieste
HTTP e da varie transazioni sul database.
Note Biografiche
E invece il business process in Seam? Michele Sciabarrà ha scritto di Java e lo ha insegnato per dieci
anni. Quando non cerca di imparare le ultime API o disquisisce
della superiorità del modello Open Source, si diletta a program-
mare cellulari Symbian in C++ e amministrare sistemi Linux.
Il contesto di business process è definito nei processi di
JBoss Seam: un
framework per il
Web 2.0
JBoss Seam è un “deep integration” framework open source nato con l’obiettivo di integrare
le tecnologie Java EE e semplificare lo sviluppo. È un framework per il Web 2.0 che offre
soluzioni native per AJAX, per il remoting, per la gestione del workflow e per il business process
management.
N
ella Java Enterprise Edition ver- degli EJB. Per far sì che alla pressione di un pulsante
sione 5.0 sono presenti le tecnolo- di submit (presente in un form HTML) venga invoca-
gie Java Server Faces (JSF) ed En- to un metodo di business (presente in un componen-
terprise Java Beans (EJB) versione te EJB) è necessario dichiarare ed implementare un
3.0. JSF è il framework di riferimen- bean JSF; il quale ha un’unica funzione: fungere da
to per realizzare applicazioni web in ponte verso la tecnologia EJB. Quindi, per integrare
Java, quindi il presentation layer; viceversa, la tecnolo- i framework JSF ed EJB è necessario “passare” per
gia EJB è lo standard con il quale implementare la lo- i backing bean che costituiscono un artificial layer che
gica di business di una applicazione, quindi il business nulla ha a che fare con le reali esigenze del business
layer. Le due tecnologie sono eccellenti nei “relativi (cfr. [JPH]).
tier” e sono necessariamente complementari in una Inoltre, per ottimizzare le operazioni di “ricerca” e le
complessa applicazione di livello enterprise. Tuttavia, modalità di invocazione dei componenti EJB, le “tra-
nella specifica JEE 5, non è presente uno standard dizionali” applicazioni Java EE fanno uso di vari desi-
per integrare i due mondi. gn pattern come il service locator, il business delegate ed il
business facade. Si può argomentare (e tutto sommato
in questi anni varie best practice lo hanno evidenziato)
Integrazione tra JSF e EJB che la separazione netta tra il presetation layer ed il bu-
siness layer porta in dote un debole accoppiamento tra
Il modello a componenti presente in JSF non si in- la view ed il business; e questo è un beneficio quando la
tegra in modo naturale con il modello a componenti logica di business è acceduta da diversi front-end.
Nella realtà, tuttavia, ciò accade raramente. Di solito
le applicazioni web fanno un uso esclusivo dei com-
ponenti EJB (in genere ad interfaccia locale) e l’ac-
coppiamento tra la view ed il business è tale che una
JBoss Seam modifica su un layer si riflette sull’altro.
è stato ideato da
JBoss Seam
Gavin King, l’ideatore di
JBoss Seam, ideato da Gavin King, l’inventore di Hi-
Hibernate bernate ([3]), propone un approccio pratico, foriero
di benefici e di semplificazioni nello sviluppo. Non ci
obbliga a non usare i design pattern precedentemen-
te citati, tuttavia il framework, fornendo un modello
a componenti uniforme (dove non vi è una distinzione tra i ture in un framework ORM è il supporto ad una politica di
componenti del presentation ed i componenti della business caricamento del tipo lazy con la quale le entità in relazione
logic), rende superfluo il codice di integrazione (glue code) vengono caricate in memoria solo quando è strettamen-
tra le diverse tecnologie. Il modello a componenti proposto te necessario (cfr. [JJ3]). Tuttavia una politica di carica-
da JBoss Seam è talmente innovativo che presso la Java mento di tipo lazy non è semplice da realizzare in un fra-
Community è in itere un processo di standardizzazione mework tradizionale MVC (Model View Controller), e per
(JSR 299, cfr. [5]). superare tale limitazione sono nati vari design pattern, tra i
Ma JBoss Seam non è “solo” un framework di integrazio- quali il più noto è il pattern Open Session In View ([6]). Per
ne. È anche un framework per il Web 2.0. Per prima cosa i necessari approfondimenti rimandiamo alla letteratura
estende i contesti di sessione e di applicazione, tipici in sul tema; tuttavia è d’obbligo evidenziare che JBoss Seam
una applicazine web, introducendo i contesti di conversa- supporta il pattern Open Session In View come default. Per-
tion e di business process, più utili per la definizione di un tanto, in una applicazione Seam è bandita l’eccezione di
flusso applicativo: tipo LazyInitializationException e le prestazioni del motore
ORM sono decisamente migliorate poiché il persistence con-
§ conversation context descrive in modo naturale un text è di tipo esteso ed agisce come cache naturale dei dati,
caso d’uso che si realizza da parte di un utente at- riducendo il round trip verso il database (cfr. [JJ3], [JPH]).
traverso varie interazioni http; Come si può intuire da quanto finora detto, l’articolo pre-
§ business process context, consente di trattare i pro- suppone una conoscenza del mondo JEE ed in particolare
cessi di business di tipo “long running” dove i del framework JSF e della tecnologia EJB versione 3.0 (ri-
task di business sono realizzati anche da diversi
utenti nel tempo.
Seam
FIGURA 3 I contesti in Seam
può anche
funzionare in assenza di Seam, deve essere univoco in tutta l’applicazione. Un com-
EJB 3.0 ponente Seam, e quindi nel nostro caso il componente di
nome “utente”, può essere direttamente referenziato dai
componenti JSF presenti nelle pagina jsp.
Per esempio, la seguente riga di codice, estratta dalla pagi-
na editUtente.jspx, collega il valore di un campo di tipo testo
al nome dell’utente:
Torniamo ad analizzare la classe Utente. Il valore specificato I contesti, ad eccezione del contesto Stateless, sono in rela-
con l’annotazione @Name, ossia il nome del componente zione gerarchica tra loro (Figura 3).
@PersistenceContext …
private EntityManager em; <f:facet name=”beforeInvalidField”>
<h:outputText value=”X”
Attraverso questa annotazione, esempio di dependency injec- styleClass=”erroreInput” />
</f:facet>
<f:facet name=”afterInvalidField”> § application.xml;
<s:message styleClass=”erroreInput” /> § jboss-app.xml
</f:facet>
<s:validateAll>
… Il codice del file application.xml, specifico di una applicazio-
<tr> ne enterprise Java, è riportato nel Listato 3; viceversa, il file
<td>Nome*</td> jboss-app.xml, come suggerisce il nome, è specifico dell’ap-
<td> plication server JBoss e specifica il class loader della appli-
<s:decorate> cazione (cfr. Listato 4).
<h:inputText value=”#{utente.nome}” Analizziamo i file di configurazione del modulo web, rubri-
required=”true”/> ca_web.war. All’interno della cartella WEB-INF sono pre-
</s:decorate> senti tre file XML di configurazione:
</td>
</tr> § web.xml;
… § faces-config.xml;
</s:validateAll> § components.xml.
…
Il primo, web.xml, è proprio di una applicazione web Java.
Osservando il codice precedente possiamo notare che, in In questo, relativamente a Seam, è definito un listener re-
presenza di un errore di validazione, prima del campo di sponsabile del bootstrapping del framework e della distru-
input è visualizzato il carattere “X”, dichiarato nel facet JSF zione dei contesti di sessione e di applicazione:
beforeInvalidField; e che dopo il campo di input è visualizza-
to il messaggio di errore vero e proprio, facet JSF afterInva- <listener>
lidField (Figura 4). <listener-class>
org.jboss.seam.servlet.SeamListener
</listener-class>
</listener>
Configurazione e packaging dell’applicazione
<?xml version=”1.0”?>
<jsp:root xmlns:jsp=”http://java.sun.com/JSP/Page”
xmlns:h=”http://java.sun.com/jsf/html”
xmlns:f=”http://java.sun.com/jsf/core”
xmlns:s=”http://jboss.com/products/seam/taglib”
xmlns=”http://www.w3.org/1999/xhtml”
version=”2.0”>
<jsp:output doctype-root-element=”html”
doctype-public=”-//W3C//DTD XHTML 1.0 Transitional//EN”
doctype-system=”http://www.w3c.org/TR/xhtml1/DTD/
xhtml1-transitional.dtd”/>
<jsp:directive.page contentType=”text/html”/>
<html>
<head>
<title>Inserisci un nuovo utente</title>
<link rel=”stylesheet” type=”text/css” href=”css/style.css” />
</head>
<body>
<f:view>
<h:form>
<f:facet name=”beforeInvalidField”>
<h:outputText value=”X” styleClass=”erroreInput” />
</f:facet>
<f:facet name=”afterInvalidField”>
<s:message styleClass=”erroreInput” />
</f:facet>
<h:messages globalOnly=”true” styleClass=”messaggio”/>
<table border=”0”>
<s:validateAll>
<tr>
<td>Nome*</td>
<td><s:decorate>
<h:inputText id=”txt_nome” value=”#{utente.nome}” required=”true”/>
</s:decorate>
</td>
</tr>
<tr>
<td>Cognome*</td>
<td><s:decorate>
<h:inputText value=”#{utente.cognome}” required=”true”/>
</s:decorate>
</td>
</tr>
<tr>
<td>Telefono*</td>
<td><s:decorate>
<h:inputText value=”#{utente.telefono}” required=”true”/>
</s:decorate>
</td>
</tr>
<tr>
<td>Indirizzo</td>
<td><s:decorate>
<h:inputText value=”#{utente.indirizzo}”/>
</s:decorate>
</td>
</tr>
</s:validateAll>
</table>
<h:commandButton value=”Salva” action=”#{rubrica.salva}”/>
</h:form>
</f:view>
</body>
</html>
</jsp:root>
<ejb-jar>
…
<interceptor-binding>
<ejb-name>*</ejb-name>
<?xml version=”1.0” encoding=”UTF-8”?> <interceptor-class>
<components
org.jboss.seam.ejb.SeamInterceptor
xmlns=”http://jboss.com/products/seam/components”
</interceptor-class>
xmlns:core=”http://jboss.com/products/seam/core”
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” </interceptor-binding>
xsi:schemaLocation=“http://jboss.com/products/seam/core …
http://jboss.com/products/seam/core-1.2.xsd </ejb-jar>
http://jboss.com/products/seam/components
http://jboss.com/products/seam/components-1.2.xsd”>
Il secondo, il file persistence.xml (cfr. [JJ3]), è necessa-
<core:init jndi-pattern=”rubrica_EAR/#{ejbName}/local”/>
<core:ejb installed=”false”/> rio per la configurazione di JPA, definendo in partico-
</components> lare Hibernate come provider:
…
<persistence>
LISTATO 5 Il file components.xml
Riferimenti e Bibliografia
<persistence-unit name=”userDatabase”>
<provider> [1]: http://www.jboss.com/.
org.hibernate.ejb.HibernatePersistence [2]: http://www.mysql.com/
</provider> [3]: http://www.hibernate.org/
<jta-data-source> [4]: JEMS Installer: http://labs.jboss.com/jemsinstaller/
java:/theDataSource [5]: Web Beans JSR 299 (http://www.jcp.org/en/jsr/detail?id=299).
</jta-data-source> [6]: Open Session In View Pattern: http://www.jroller.com/cardsharp/
<properties> entry/open_session_in_view_pattern
<property [7]: Download Jboss Seam: http://www.jboss.com/products/seam
name=»hibernate.hbm2ddl.auto» [JJ1] : “Speciale JSF”. Java Journal N. 1
value=»create-drop»/> [JJ2a] : “Introduzione agli EJB 3.0”. Java Journal N. 3.
</properties> [JJ2b] : “Orizzonti Enterprise” Java Journal N. 3.
</persistence> [JJ3] : “JPA (prima parte)”. Java Journal N. 4.
… [JSF]: De Mann, Kito, “JavaServer Faces In Action”, Manning Publica-
tions Co 2005.
Prima di concludere osserviamo che nell’archivio rubrica_ejb.jar è [MEJ]: Sriganesh R. P., Brose G., Silverman M. “Mastering Enterprise
presente il file seam.properties. La cosa curiosa è che il file è vuoto ed è JavaBeans 3.0”, Wiley Publishing, Inc.
tuttavia fondamentale! Infatti allo startup Seam cerca i suoi componenti [BAD]: Kodali Raghu R., Wetherbee J. e Zadrozny P., “Beginning EJB
(le classi annotate con @Name) in tutti gli archivi che contengono un 3 Application Development”, Apress.
file, anche vuoto, il cui nome è appunto seam.properties. [JPH]: Bauer C. e King G., “Java Persistence with Hibernate”, Manning
Publications Co.
Conclusioni Note Biografiche
In questo articolo abbiamo iniziato ad apprezzare i benefici introdotti Fabio Staro, dottore in Fisica è Responsabile Tecnico per i pro-
getti Java presso la Direzione Ricerca ed Innovazione di Engi-
con JBoss Seam. Abbiamo anche accennato al concetto di conversa- neering Ingegneria Informatica S.p.A.
zione utente (conversation context) e alla relativa gestione.
solo
15,00
Euro
www.shopinfomedia.com
JAVA Journal educational
DAO Generator
Realizzare un’applicazione Web resistente alle migrazioni tra DBMS
N
on sempre, quando iniziamo a scri- DAO Generator
vere un progetto, sappiamo se use-
remo per sempre un determinato Quando si progettano applicazioni suddivise in di-
DBMS, oppure se nel corso del tem- versi tier (Presentation/Business/Data Access/Value
po cambierà. Object) una tra le operazioni più gravose consiste
A priori, di conseguenza, converreb- nella configurazione e nella creazione dei Data Ac-
be premunirsi da questi cambiamenti disegnando cess Object (DAO), che spesso sono il vero “core” del-
un’architettura robusta e con dei package di imple- l’applicazione. Ma per scrivere bene i DAO lo sforzo è
mentazione facilmente intercambiabili. notevole, soprattutto quando sia le tabelle sia i cam-
Infatti, a meno che non si stiano utilizzando prodotti pi sono in numero elevato. Infatti, i passi da esegui-
come Hybernate (che si interpone come middlewa- re sono:
re parlando nel dialetto SQL del DBMS che dobbia-
mo utilizzare), abbiamo bisogno per ogni DBMS di
un “matching” appropriato tra SQL e tipi di dati, dal § costruire oggetti Java che rispecchiano la
DBMS a JAVA. Ovviamente, senza le giuste accor- struttura delle tabelle e degli attributi del
tezze in fase di progettazione, il refactoring del Da- DB;
taLayer comporta problemi e costi di manutenzione § scrivere per ogni tabella e per ogni chiave
elevatissimi; inoltre, non rimane traccia della vecchia primaria del DB un Value Object (VO);
versione della nostra implementazione se non in ob- § scrivere un’interfaccia con i metodi (e le ec-
soleti backup. cezioni) relativi ad ogni singola tabella;
La soluzione
A partire da 4 tabelle
FIGURA 4 Specifica delle credenziali di accesso al database
con 19 attributi
DAO Generator ha
prodotto 39 file Java
FIGURA 5 Messaggio di avvenuta connessione
Connection Factory
java.sql.Connection
ConnectionInterface factory =
public class MySQLConnection implements (ConnectionInterface)c.cast(c.newInstan
ConnectionInterface ce());
{
Class.forName(
ProjectConstant.DBMS_MYSQL_DRIVER);
e così via per gli altri tipi di DBMS.
String url = ProjectConstant.DBMS_MYSQL_URL; Se ci sono stati dei problemi il metodo prov-
vederà a inviare l’eccezione, altrimenti pas-
conn = DriverManager.getConnection( serà semplicemente la connessione al meto-
url,username, password); do chiamante.
return conn;
} Partendo da questo presupposto, per poter
}
asserire di aver fornito un buon servizio di
connessione trasparente anche a livello di
LISTATO 2 La classe MySQLConnection
Business, servirebbe un metodo che in auto-
istanziare l’apposita classe di connessione. È una scelta matico restituisca la connessione di default
più dispendiosa, ma che non necessita di manutenzione. scelta dall’amministratore o dallo sviluppatore del siste-
Infatti, in questo modo il codice può diventare: ma, senza dover ogni volta conoscere e inserire le informa-
zioni necessarie. Un modo semplice ed elegante è ricorrere
public Connection getConnection(String DBMSName) ancora una volta a un file di costanti e prelevare la connes-
throws ConnectException,ClassNotFoundException, sione di default scelta dall’utente e sfruttarla all’interno
SQLException,InstantiationException, della logica di un metodo:
IllegalAccessException
{ public Connection getDefaultConnection() throws
Class c = Class.forName( ConnectException,
ProjectConstant.DBMS_PREFIX + ClassNotFoundException,
DBMSName + SQLException,
ProjectConstant.DBMS_SUFFIX); InstantiationException,
ConnectionInterface factory = IllegalAccessException
(ConnectionInterface)c.cast(c.newInstance()); {
Connection connection = factory.connect(); return getConnection(
return connection; ProjectConstant.DBMS_CONNECTION);
} }
CacheManager
DAOFactory daoFactory =
(DAOFactory)cache.get public static final String DBMS_CONNECTION =
(“DAO_FACTORY”); getPropValue(“dbms.connection”);
//MYSQL
public static final String
DBMS_CONNECTION = “MySQL”;
Interazione tra i componenti public static final String
DBMS_MYSQL_USERNAME = “root”;
A questo punto possiamo radu- public static final String
DBMS_MYSQL_PASSWORD = “password”;
public static final String
DBMS_MYSQL_DRIVER =
nare tutti i concetti esposti fino-
“com.mysql.jdbc.Driver”;
ra e vedere come sarà semplice public static final String DBMS_MYSQL_URL =
realizzare delle classi di Presen- “jdbc:mysql://localhost:3306/javacourse”;
tation ben strutturate.
Nella semplice classe di Action //ORACLE
Struts riportata nel Listato 8 ci // analogo ...
sono tutti i concetti evidenziati public static final String DBMS_ORACLE_USERNAME = “…”;
finora. public static final String DBMS_ORACLE_PASSWORD = “…”;
A partire dal recupero dei dati public static final String DBMS_ORACLE_DRIVER = “…”;
nel CacheManager, vediamo public static final String DBMS_ORACLE_URL = “…”;
public static final String DBMS_PREFIX = “…”;
come il daoFactory ci permetta,
public static final String DBMS_SUFFIX = “…”;
con dei semplici comandi, di ot-
tenere delle funzionalità di alto
livello; infatti, daoFactory.createBo
okDAO() crea il BookDAO relati- LISTATO 5 Costanti utilizzate nella classe ProjectConstant
vo al DBMS selezionato prece-
dentemente dall’utente (attra- public abstract class DAOFactoryCreater implements DAOFactory
verso l’utilizzo del file di costan- {
ti) in modo del tutto trasparente
per l’utente. Come si può notare, private static DAOFactoryCreaterNew
non appare nessun riferimento getDAOFactory(String dbType)
al DBMS. {
if(dbType.equals(ProjectConstant.DBMS_CONNECTION_MYSQL)){
Il metodo invocato di BookDAO,
return new DAOFactoryImplMySQL();
findAll(connection), necessita so- }
lamente della connessione, assi- else if(dbType.equals(
curando, così come detto prece- ProjectConstant.DBMS_CONNECTION_ORACLE)){
dentemente, una corretta gestio- return new DAOFactoryImplOracle();
ne della connessione, in quanto }
l’istanza, la gestione delle ecce- else{
zioni e la chiusura della connes- return new DAOFactoryImplMySQL();
sione vanno gestiti ad alto livello }
e non nei singoli metodi. }
Con una sola riga di codice ab-
public static DAOFactoryCreater getFactory(){
biamo ottenuto l’elenco dei Libri return getDAOFactory(ProjectConstant.DBMS_CONNECTION);
presenti in archivio. }
DAOGen gestisce gli oggetti }
multipli come Array di oggetti;
dato che per il lato presentation
gli array sono a volte ingestibi- LISTATO 6 La classe DAOFactory
li con alcuni framework, è stato
adottato un metodo di utilità che converta gli Array di og- Avendo implementato le factory in modo da rimandare
getti in ArrayList di oggetti le eccezioni al livello superiore, la gestione delle eccezio-
ni viene effettuata solamente in tutte le classi di presen-
JavaUtils.getArraylistFromArray(books); tation; assicurando così una gestione centralizzata note-
volmente semplificata. Infatti, in questo modo è possibile
personalizzare il messaggio di errore in base al tipo di ec-
in modo da passare infine il risultato nella request con il cezione scatenata e rimandare l’errore stesso al client dal-
comando: l’opportuna pagina di errore.
Quando si progettano applicativi basati sull’utilizzo di dati
request.setAttribute(“results”, results); provenienti da database, uno tra i concetti più importanti
è la chiusura della connessione dopo il suo utilizzo, come
abbiamo già detto.
if(!cache.containsValue(name)){
cache.put(name, value);
session.setAttribute(“SESSION”, cache);
return cache;
}
session = request.getSession();
if(session.getAttribute(“SESSION”) == null ||
session.getAttribute(“SESSION”).equals(“”))
{
//insert Connection
connection = new Connection Factory().getDefaultConnection();
cache.put(“CONNECTION”, connection);
//insert DAOFactory
daoFactory = DAOFactoryCreaterNew.getFactory();
cache.put(“DAO_FACTORY”, daoFactory);
session.setAttribute(“SESSION”, cache);
}
return cache;
}
}
try {
} catch (ConnectException e) {
request.setAttribute(“error”, e);
e.printStackTrace();
} catch (ClassNotFoundException e) {
request.setAttribute(“error”, e);
e.printStackTrace();
} catch (SQLException e) {
request.setAttribute(“error”, e);
e.printStackTrace();
} catch (InstantiationException e) {
request.setAttribute(“error”, e);
e.printStackTrace();
} catch (IllegalAccessException e) {
request.setAttribute(“error”, e);
e.printStackTrace();
}
finally {
try {
result = “failure”;
request.setAttribute(“error”, e);
e.printStackTrace();
finally{
return mapping.findForward(result);
}
}
}
}
<html>
<body>
<logic:present name=”results”>
<logic:notEmpty name=”results”>
<table border=”1”>
<tr>
<td align=”center”>ID</td>
<td align=”center”>NAME</td>
<td align=”center”>PRICE (�)</td>
</tr>
<logic:iterate id=”book” name=”matrix”>
<tr>
<td>
<a href=”books.do?action=findById&id=<bean:write name=”book” property=”id” />”>
<bean:write name=”book” property=”id” /></a>
</td>
<td><bean:write name=”book” property=”name” /></td>
<td><bean:write name=”book” property=”price” /></td>
</tr>
</logic:iterate>
</table>
</logic:notEmpty>
<logic:empty name=”results”>
La ricerca non ha prodotto risultati
</logic:empty>
</logic:present>
<logic:notPresent name=”results”>
Nessun oggetto presente.
</logic:notPresent>
</body>
</html>
dalle nostre action. Per la Action in questione, adottando DAOGen, nonostante generi Array di oggetti e non Collec-
le Tag Libraries di Struts, la pagina di visualizzazione per tions (operando così in vecchio stile), si può considerare a
l’elenco degli Items (Listato 9) produrrà un aspetto simile tutti gli effetti uno strumento indispensabile di generazio-
a quanto è mostrato nella Figura 13. ne DAO (per chi ragiona secondo questo pattern) anche
perché ci può aiutare facilmente, durante le fasi di proget-
E anche il corpo del metodo Action “findById” sarà analo- to, nelle modifiche strutturali al DB, senza impattare sulle
go (Listato 10), così come la pagina di dettaglio (Listato funzionalità di alto livello, grazie all’utilizzo delle opportu-
11 e Figura 14). ne Factory di creazione dei DAO.
Gli argomenti trattati in questo articolo sono tanti e di si-
Conclusioni curo hanno bisogno di essere assimilati con la pratica: il
punto fondamentale è notare come Java, al solito, fornisca
Nonostante la complessità di strutturazione delle factory gli strumenti per realizzare sistemi complessi in termini di
necessarie per ottenere dei metodi di alto livello, l’archi- funzionalità, ma di semplice utilizzo per lo sviluppatore fi-
tettura così creata fornisce in fase di sviluppo innumere- nale. Il tutto facendo colloquiare più sistemi di piccole di-
voli benefici: buona visibilità del codice, manutenibilità, mensioni ma con funzionalità e scopi ben definiti.
estendibilità e una completa gestione delle eccezioni; ga- Le nozioni fornite, se pur basilari nella loro implementa-
rantendo così una distinta robustezza dell’applicazione. zione, sono una buona base per realizzare applicazioni web
Attraverso questi concetti, se sfruttati bene, non è diffi- su cui potranno intervenire più sviluppatori, ma avendo ri-
cile ottenere dei package riusabili da adottare nei nostri spettato gli standard. Buon lavoro a tutti.
progetti: dal package delle connessioni, al DAOFactory, a
quello di CacheManager o alla JavaUtil che trasforma gli Riferimenti
Array in ArrayList.
In questo modo al programmatore finale sarà fornito un DAO Generator: https://dao-generator.dev.java.net/
framework a tutti gli effetti, attraverso il quale, con po-
Note Biografiche
che righe, potrà gestire rapidamente e con estrema puli-
zia l’intero progetto, evitando di incappare negli errori più Riccardo Solimena si occupa di sviluppo Java. Gestisce il sito
www.riccardosolimena.com.
comuni.
JPA: Java
Persistence API
seconda parte
La specifica JPA fornisce uno standard per la persistenza dei dati in Java, semplificando
radicalmente la precedente tecnologia degli EJB di tipo Entity Bean. Tuttavia JPA non è
una reingegnerizzazione della precedente tecnologia ma è di fatto una nuova architettura
N
el precedente articolo su JPA (acro-
nimo di Java Persistence Api) [1] ab- Tra le classi Prodotto e Autore è presente una relazione
biamo introdotto le caratteristiche molti a molti bidirezionale. E tra le classi Autore ed In-
base della specifica ed abbiamo ap- dirizzo è presente una relazione uno a uno unidirezio-
profondito la gestione delle relazioni nale. La specifica JPA, per supportare in un database
tra le entità. Nell’articolo risaltava in relazionale il concetto di ereditarietà, offre varie stra-
modo prepotente la radicale semplificazione presente tegie di mapping. Queste sono specificate nella enu-
con JPA rispetto alla precedente specifica per la per- merazione javax.persistence.InheritanceType:
sistenza dei dati in Java: gli Entity Bean versione 2.x.
In questo articolo, conclusivo sull’argomento, appro- • SINGLE_TABLE;
fondiamo ulteriormente la specifica soffermandoci • JOINED;
sulle strategie di mapping per la gestione della ere- • TABLE_PER_CLASS;
ditarietà, un design pattern frequente nel paradigma di
sviluppo object-oriented e non presente nel mondo In questo articolo analizzeremo le prime due strate-
relazionale dei database. Gli esempi riportati realiz- gie per il mapping delle entità tralasciando la strate-
zano un processo di sviluppo top-down: ossia, par- gia TABLE_PER_CLASS in quanto il suo supporto da
tendo dal modello delle classi deriveremo il disegno parte dei provider JPA non è obbligatorio nella attua-
delle tabelle. le versione della specifica.
Gli esempi sono stati verificati con l’application ser-
ver JBoss versione 5.0 [2], con il database MySQL
versione 5.0.27 [3] e con il provider JPA Hibernate La strategia SINGLE_TABLE
[4].
Iniziamo con l’approfondire la strategia di mapping
SINGLE_TABLE. Questa è la strategia di default, dove
Strategie per l’ereditarietà una sola tabella è usata per rappresentare l’intera ge-
rarchia delle classi. Una colonna della tabella, assu-
Gli esempi che desideriamo realizzare sono voluta- mendo valori differenti in base al tipo Java rappre-
mente semplificati, al fine di approfondire l’API e sentato dal record, è usata come discriminante per
l’architettura JPA eliminando le complessità applica- distinguere tra le sottoclassi della gerarchia.
tive legate ad un particolare dominio di interesse. Os- Di seguito riportiamo uno stralcio del codice della
servando il diagramma delle classi riportato in Figu- classe Prodotto:
ra 1 possiamo notare la semplice gerarchia presente
tra le classi: Prodotto, Libro, Video, DVD e VHS. In par-
ticolare, la classe astratta Prodotto è la root class della @Entity(name=”Prodotto_Single”)
gerarchia e le classi Libro e Video la estendono diretta- @Table(name=”PRODOTTO_SINGLE”)
mente. La classe Video è a sua volta astratta ed è este- @Inheritance(strategy=InheritanceType.SINGLE
sa dalle classi concrete DVD e VHS. _TABLE)
@DiscriminatorColumn(name=”DISC”, @DiscriminatorValue(“LIBRO”)
discriminatorType=DiscriminatorType.STRING) public class Libro extends Prodotto
public abstract class Prodotto {
{ ...
... private int numeroPagine;
@Id private boolean edizioneEconomica;
@GeneratedValue(strategy=GenerationType.AUTO) ...
private int id; }
private String titolo;
private Date annoProduzione;
@ManyToMany(cascade=CascadeType.ALL, Ecco uno stralcio del codice della classe Video,
fetch=FetchType.LAZY,
targetEntity=Autore.class) @Entity(name=”Video_Single”)
private Set<Autore> autori = null; public abstract class Video extends Prodotto
... {
} ...
private boolean colore;
...
Osservando il codice della classe Prodotto è possibile no- }
tare l’uso delle annotazioni @Inheritance e @Discrimina-
torColumn. Attraverso l’annotazione @Inheritance è possi- e della classe VHS,
bile specificare la strategia di mapping, nell’esempio SIN-
GLE_TABLE. L’annotazione @DiscriminatorColumn consen- @Entity(name=”VHS_Single”)
te di specificare il nome, nell’esempio “DISC”, e il tipo del- @DiscriminatorValue(“VHS”)
la colonna che funge da discriminante nel distinguere le public class VHS extends Video
sottoclassi della catena gerarchica. Di seguito riportiamo i {
frammenti di codice significativi per le altre classi della ge- ...
rarchia. Iniziamo con uno stralcio del codice sorgente del- private String tipoNastro = null;
la classe Libro: ...
}
@Entity(name=”Libro_Single”)
<persistence>
<persistence-unit name=”GestioneBiblioteca”>
<jta-data-source>java:/theDataSource</jta-data-source>
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>it.articolo.jpa2.Prodotto</class>
<class>it.articolo.jpa2.Libro</class>
<class>it.articolo.jpa2.Video</class>
<class>it.articolo.jpa2.VHS</class>
<class>it.articolo.jpa2.DVD</class>
<class>it.articolo.jpa2.Autore</class>
<class>it.articolo.jpa2.Indirizzo</class>
<exclude-unlisted-classes/>
<properties>
<property name=”hibernate.show_sql” value=”true”/>
<property name=”hibernate.format_sql” value=”true”/>
<property name=”hibernate.hbm2ddl.auto” value=”create”/>
</properties>
</persistence-unit>
</persistence>
hibernate.hbm2ddl.auto
A parte la colonna “DISC” e la colonna ID che è la chiave Considerazioni preliminari sulle strategie di mapping
primaria, tutte le altre colonne della tabella possono assumere il
valore NULL. Questo è necessario, in quanto un record del- Quale strategia di mapping applicare ad una gerarchia di
la tabella può rappresentare una qualsiasi classe presente classi? La risposta a questa domanda non è semplice, in
nella gerarchia. Se, per esempio, avessimo mappato l’attri- quanto varia in funzione del risultato che si desidera otte-
buto “contenutiSpeciali” della classe DVD su una colonna nere: per esempio, prestazioni adeguate o maggiore fles-
dichiarata come NOT NULL sarebbe stato impossibile per- sibilità durante le fasi di design e/o deployment. Di seguito
sistere un oggetto delle classi Libro e VHS… cercheremo di delineare alcune linee guida, ben consci che
tali indicazioni sono preliminari e che necessitano di una
sperimentazione sul campo, specifica al proprio contesto.
La strategia JOINED
Analizziamo ora la strategia di mapping di tipo JOINED. Applicazione della strategia SINGLE_TABLE
A livello di codice Java le classi Prodotto, Libro, Video, VHS
e DVD non variano, a parte il valore assegnato alla anno- La strategia di mapping SINGLE_TABLE è consigliata in
tazione @Inheritance. Di seguito uno stralcio del sorgente presenza di una gerarchia stabile e sostanzialmente sem-
delle classe Prodotto e Libro: plice e poco “profonda”. Infatti aggiungere una nuova
classe alla gerarchia o aggiungere nuovi attributi a qualche
@Entity(name=”Prodotto_Joined”) classe preesistente nella gerarchia porta alla creazione di
@Table(name=”PRODOTTO_JOINED”) nuove colonne nella tabella di mapping. Pertanto una ge-
@Inheritance(strategy=InheritanceType.JOINED) rarchia molto estesa può condurre alla generazione di una
public abstract class Prodotto tabella con un numero di colonne elevato con la conseguenza
{...} di un impatto negativo sul “layout” della tabella e del data-
base in generale. Sempre in relazione al “layout” della ta-
@Entity(name=”LIBRO_JOINED”) bella di mapping è opportuno ricordare che le colonne del-
public class Libro extends Prodotto la tabella mappate sugli attributi delle classi della gerar-
{...} chia devono poter assumere il valore NULL. Inoltre, se per
qualche motivo vi è la necessità di mappare uno o più attri-
buti in colonne di tipo LOB può essere necessario mappare
La struttura delle tabelle che deriva dal modello delle clas- l’entity class non più su una sola tabella ma su più tabelle
si è riportata in Figura 3. Per ogni entità della gerarchia è attraverso l’annotazione @SecondaryTable. Relativamen-
generata una tabella le cui colonne sono solo gli attributi te alle prestazioni, poiché generalmente si è in presenza di
esplicitamente dichiarati nella classe. La root class della ge- una singola tabella, le operazioni di ricerca sui diversi tipi
rarchia è mappata su una root table (in Figura 3 la tabella della gerarchia o su uno specifico tipo risultano efficienti,
PRODOTTO_JOINED) nella quale è definita la chiave pri- non essendo richieste operazioni di JOIN tra tabelle.
maria poi usata in tutte le tabelle della gerarchia. Ogni ta-
bella nella gerarchia definisce una chiave primaria uguale
alla chiave primaria della root table e definisce una foreign
key (chiave esterna) verso la chiave primaria della root ta-
ble.
Applicazione della strategia JOINED in JPA. Infatti, il linguaggio è object-oriented, usando nella
sua sintassi le entity class e le regole di navigazione definite
La strategia di mapping di tipo JOINED offre una buona tra le entità, ed è indipendente dal database. Al contrario,
flessibilità durante le fasi di design e di deployment. Infat- il linguaggio SQL, pur esistendo uno standard, è di fatto
ti, l’aggiunta o la rimozione di uno o più attributi ad una coniugato in diversi “dialetti” caratteristici di ogni data-
classe presente nella gerarchia coinvolge nella modifica base che non ne garantiscono la portabilità (vendor lock-in).
solo la tabella che specificatamente rappresenta la classe; Per ottenere una istanza dell’oggetto Query è possibile in-
mentre l’introduzione di una nuova classe nella gerarchia vocare sull’oggetto EntityManger o il metodo createQuery()
porta semplicemente alla creazione di una nuova tabella nel- o il metodo createNativeQuery(). Il primo metodo usa il lin-
lo schema. Relativamente alle prestazioni, una operazione guaggio EJB QL per la definizione dello statement mentre il
di ricerca tra le entità della gerarchia necessiterà di una o secondo metodo usa il linguaggio SQL. Per esempio, con
più operazioni di JOIN anche in funzione della “profon- riferimento alla Figura 2, per ottenere tutti i prodotti è
dità” della gerarchia. Pertanto la presenza di un numero possibile scrivere:
elevato di sottoclassi può avere un impatto negativo sulle
prestazioni. public List<Prodotto> getProdotti()
{
Query query = entityManager.createQuery(“SELECT
Una API per le query con JPA
o FROM Prodotto_Single o”);
La specifica JPA definisce un linguaggio per eseguire le return query.getResultList();
query sulle entità ed il loro stato persistente. Il linguag- }
gio consente allo sviluppatore di specificare la semantica
di una query in modo portabile ed indipendente dallo spe-
cifico database presente nella propria infrastruttura tecno- L’espressione che rappresenta lo statement di una query
logica. Con JPA si è in presenza di una radicale estensione può essere ricavata a runtime, ossia durante l’esecuzione
del linguaggio EJB QL definito nella precedente specifica del programma, come di fatto accade nell’esempio prece-
per gli EJB di tipo Entity Bean versione 2.1 [5]. dente; o può essere dichiarata in un file di configurazione
Nel precedente articolo su JPA [1] abbiamo osservato come della applicazione. Nel primo caso si è in presenza di una
attraverso l’oggetto EntityManager è possibile fare semplici query dinamica, nel secondo di una query statica o di una na-
operazioni di ricerca attraverso il metodo find(). La firma med query. Le query statiche sono dichiarate attraverso la
del metodo è: annotazione @NamedQuery. Per esempio, la query prece-
dente può divenire una named query dichiarandola come
public <T> T find(Class<T> entityClass, Object annotazione del sorgente della classe Prodotto:
primaryKey);
@Entity(name=”Prodotto_Single”)
Il metodo accetta come parametro di input il tipo della en- ...
tity class di cui tornarne una istanza ed un oggetto che rap- @NamedQuery(name = “Prodotto.findAll”,
presenta la chiave primaria e restituisce l’istanza della en- query = “SELECT o
tity class di data chiave primaria. Il metodo è pratico e allo FROM Prodotto_Single o”)
stesso tempo semplice. Tuttavia nei progetti è necessario, public abstract class Prodotto implements
la maggior parte delle volte, eseguire query complesse la Serializable
cui esecuzione restituisce, eseguendo operazioni di JOIN e {
condizioni di WHERE articolate, una o più istanze di enti- ...
ty class. In questi casi è necessario usare un oggetto di tipo }
Query, definito nel package javax.persistence e la sintassi
estesa del linguaggio EJB QL. I passi essenziali per creare
un oggetto Query ed eseguire una query sono schematizza- Per usare una named query il metodo precedente diviene:
ti di seguito:
public List<Prodotto> getProdotti()
• Recuperare dall’Entity Manager una istanza della {
classe javax.persistence.Query; Query query = entityManager.createNamedQuery(
• Impostare i parametri necessari all’esecuzione “Prodotto.findAll”);
della query; return query.getResultList();
• Eseguire effettivamente la query. }
come segue:
@TransactionAttribute(
@NamedQuery(name = “Prodotto.findByTitolo”, TransactionAttributeType.REQUIRES_NEW)
query = “SELECT o public void bulkUpdate(String entityName)
FROM Prodotto_Single o {
WHERE o.titolo = :TITOLO”) String dOperation = “UPDATE “+entityName+” t
SET t.annoProduzione = :ANNO_PRODUZIONE”;
Query q = entityManager.createQuery(dOperation);
ed un metodo che la usa: q.setParameter(“ANNO_PRODUZIONE”, null);
q.executeUpdate();
public List<Prodotto> getProdottiByTitolo(String }
titolo)
{ @TransactionAttribute(
Query query = entityManager.createNamedQuery( TransactionAttributeType.REQUIRES_NEW)
“Prodotto.findByTitolo”); public void bulkDelete(String entityName)
query.setParameter(“TITOLO”, titolo); {
return query.getResultList(); Query q = entityManager.createQuery(
} “DELETE FROM “+entityName);
q.executeUpdate();
}
In precedenza abbiamo osservato come il linguaggio per In particolare, con riferimento alla Figura 2, il metodo
eseguire le query definito nella specifica JPA sia una esten- bulkUpdate() imposta il valore della colonna “anno di pro-
sione del linguaggio EJB QL. In particolare, introduce varie duzione” presente nella tabella PRODOTTO_SINGLE al va-
migliorie che di seguito accenniamo: lore null; mentre il metodo bulkDelete() elimina tutti i re-
cord rappresentati da una entity class. Osserviamo che se
• Aggiornamenti e cancellazioni “massive”; si invocato i metodi bulkUpdate() e bulkDelete() passando
• Operazioni di JOIN; come parametro di input il valore “Libro_Single”, ossia il
• Parole chiave GROUP BY e HAVING; nome della entity class Libro, sono aggiornati ed eliminati
• Projection; i record relativi ad un libro; viceversa, se si invocano i due
• Subquery. metodi passando come parametro di input il valore “Pro-
dotto_Single”, ossia il nome della entity class Prodotto (la
Operazioni massive root class della gerarchia), sono aggiornati ed eliminati tutti
i record relativi ad un libro, ad un video di tipo DVD e ad
Per aggiornamenti e cancellazioni “massive” indichiamo un video di tipo VHS.
una singola operazione il cui risultato è l’eliminazione o
aggiornamento di un numero, anche elevato, di entità (in
inglese i termini per indicare queste caratteristiche sono Operazioni di JOIN
bulk update e bulk delete). Quando si esegue una operazione
di cancellazione o di aggiornamento “massivo” valgono le Analizziamo ora il supporto introdotto in JPA per la gestio-
seguenti regole: ne delle operazioni di JOIN. Con JPA possiamo avere i se-
guenti tipi di JOIN:
• L’operazione “massiva” si applica all’entità
“sorgente” della bulk operation e a tutte le • JOIN;
sottoclassi di questa; • LEFT JOIN;
• L’operazione non si propaga alle entità • FETCH JOIN.
relazionate con l’entità “sorgente” della
bulk operation; Per esempio, sempre con riferimento alla Figura 2, se vo-
• Il persistence context non è sincronizzato con lessimo trovare tutti i prodotti che hanno associato almeno
il risultato della operazione. un autore potremmo scrivere la JOIN:
@NamedQuery(name=”prodottiByAutoreFETCH_JOIN”,
query=”SELECT o FROM Prodotto_Single o
Conclusioni
JOIN FETCH o.autori”)
Con questo articolo concludiamo la panoramica sulla spe-
cifica JPA. Non è stato possibile trattare tutte le caratte-
Parole chiave GROUP BY e HAVING ristiche della persistence API, tuttavia sono evidenti due
peculiarità: da un lato la semplicità di JPA come prodotto
Nella precedente specifica di EJB QL era assente il suppor- ORM (Object Relational Mapping) e dall’altro l’estrema fles-
to per le parole chiave GROUP BY e HAVING di SQL. Nella sibilità dell’API con il mapping delle relazioni e della ere-
attuale specifica JPA tale supporto è stato introdotto: per- ditarietà. Sarà il tempo a dirci se JPA diverrà la modali-
tanto è possibile scrivere query che specificano raggruppa- tà standard e più diffusa, tra sviluppatori e architetti del
menti e condizioni tramite queste keyword. Per esempio software, per persistere gli oggetti in Java. Tuttavia, per
per ottenere i conteggi del numero di video, sia VHS che quanto si è detto e per la diffusione di Hibernate e TopLink
DVD, che sono a colori ed in bianco e nero possiamo scri- (genitori naturali di JPA), le premesse sono estremamen-
vere: te positive.
@NamedQuery(name=”contaVideo”,
Riferimenti
query=”SELECT o.colore,
COUNT(o) FROM Video_Single o [1] : JPA (prima parte). Java Journal N. 4, anno I.
GROUP BY o.colore”) [2]: http://www.jboss.com/.
[3]: http://www.mysql.com/
[4]: http://www.hibernate.org/
Proiezioni [5] : Enterprise JavaBeans, v 2.1. http://java.sun.com/
products/ejb
Con il termine Projection la specifica indica la possibilità
che nel risultato di una query siano presenti solo alcuni at- Bibliografia:
tributi di una entità o di un insieme di entità. Si tratta di
una ottimizzazione nel caso ad un client non interessi la- [MEJ]: Mastering Enterprise JavaBeans 3.0, edito dalla Wiley
vorare con la totalità degli attributi di una entità, ma solo Publishing, Inc. Autori: Rima Patel Sriganesh, Gerald Bro-
con un sottoinsieme. Per esempio, se avessimo necessità di se, Micah Silverman.
un elenco con solo i titoli e l’anno di produzione dei pro- [BAD]: Beginning EJB 3 Application Development, edito dalla
dotti possiamo scrivere: Apress. Autori: Raghu R. Kodali and Jonathan Wetherbee
with Peter Zadrozny
@NamedQuery(name=”findWithProjection”,
query=”SELECT o.titolo,
o.annoProduzione FROM Prodotto_Single o”)
COMMUNITY WATCH
Il JUG Torino
Ü di Stefano Sanna
(stefano.sanna@javajournal.it)
Java Journal: Prima di tutto, ci dici in due parole chi è Bruno Bos-
sola?
JJ: Quali, invece, le limitazioni che Java dovrebbe superare? Ringraziamo Bruno Bossola per il tempo che ci ha dedicato e
per l’impegno suo e di tutto il JUG Torino nel promuovere Java
BB: Java dovrebbe innanzitutto lavorare su alcune librerie di nel nostro Paese.
base che attualmente incorpora nel core, cercando di eliminar-
le o riscriverle. Innanzitutto il Collections framework: una cosa
veramente triste; viola pressoché tutti i principi OO che cono-
sco (pensate ad esempio alla sostituibilità e alle famigerate Un- [1] http://java-champions.dev.java.net/
supportedOperationException); soffre di una progettazione ve- [2] http://it.newinstance.it/
ramente povera (pensate ai tristissimi iteratori esterni: ma i [3] http://www.jugtorino.it/vqwiki/jsp/Wiki?StoriaDelJug
blocchi di SmallTalk proprio li abbiamo dimenticati?); e man- [4] http://www.jugtorino.it/vqwiki/jsp/Wiki?JavaDayAtSchool
ca anche secondo me di una metafora uniforme (è così difficile [5] http://www.javapolis.com
pensare alle liste come delle mappe in cui la chiave è l’indice?). [6] http://www.jazoon.com
Passiamo ora a Swing: a me sembra un campionato di overdesi- [7] http://java.sun.com/docs/books/tutorial/
gn! Insomma, alla fine dobbiamo aprire delle finestre con den- [8] http://www.jugtorino.it/vqwiki/jsp/Wiki?Blog
education@infomedia.it
OFFERTE ABBONAMENTI
2008
ABBONAMENTO ANNUALE
WEB Cartaceo
2 a scelta 80,00€
3 a scelta 120,00€
4 a scelta 170,00€
5 a scelta 220,00€
CAP _____________ Città ___________________________________ Prov. ______ CAP ____________ Città _________________________________ Prov. _________
• I prezzi degli abbonamenti Web sono conprensivi dell’ IVA al 20% MODALITA’ DI PAGAMENTO
• I prezzi degli abbonamenti per l’estero sono maggiorati di spese di spedizione. � Allego fotocopia del Bonifico Bancario effettuato sul C/C 000000014804
CAB 25200 ABI 01030 Cin “A” - Monte dei Paschi di Siena - Agenzia di Perignano
• Gli abbonamenti decorrono dal primo numero raggiungibile. IBAN IT84A0103025200000000014804
Per attivazioni retroattive contattaci al numero 0587/736460 o invia una e-mail
all’indirizzo: abbonamenti@gruppoinfomedia.it � Allego fotocopia della ricevuta del versamento sul C/C Postale N.14291561 intestato
a: “Gruppo Editoriale Infomedia S.r.l. - Ponsacco” IBAN IT84X0760114000000014291561
Garanzia di riservatezza - Gruppo Editoriale Infomedia garantisce la massima riservatezza dei dati da lei forniti e la possibilità di richiederne gratuitamente la rettifica
o la cancellazione scrivendo a: Responsabile Dati - Gruppo Editoriale Infomedia Srl - Via Valdera P. 116 - 56038 Ponsacco (PI). Le informazioni custodite nel nostro
archivio elettronico verranno trattate in conformità alla legge 196/03 sulla tutela dati personali.
L’IVA sul prezzo dell’abbonamento cartaceo è assolta dall’Editore e non sussiste l’obbligo di emissione della fattura, ai sensi del D.M. 9 aprile 1993, art.1, comma 5;
pertanto, ai fini contabili, farà fede la sola ricevuta di pagamento; perciò la fattura verrà emessa solo se esplicitamente richiesta al momento dell’ordine.
Lei può dedurre il costo dell’abbonamento dal reddito d’impresa e dai redditi derivanti dall’esercizio di arti e professioni (artt. 54 e 56 del TUIR)
solo
12,90
Euro
l e , t r u c c hi e c o nsigli
Scopri rego
c o m u n i c ar e v i a I nternet
per
www.shopinfomedia.com