Mokabyte

Dal 1996, architetture, metodologie, sviluppo software

  • Argomenti
    • Programmazione & Linguaggi
      • Java
      • DataBase & elaborazione dei dati
      • Frameworks & Tools
      • Processi di sviluppo
    • Architetture dei sistemi
      • Sicurezza informatica
      • DevOps
    • Project Management
      • Organizzazione aziendale
      • HR
      • Soft skills
    • Lean/Agile
      • Scrum
      • Teoria della complessità
      • Apprendimento & Serious Gaming
    • Internet & Digital
      • Cultura & Società
      • Conferenze & Reportage
      • Marketing & eCommerce
    • Hardware & Tecnologia
      • Intelligenza artificiale
      • UX design & Grafica
  • Ultimo numero
  • Archivio
    • Archivio dal 2006 ad oggi
    • Il primo sito web – 1996-2005
  • Chi siamo
  • Ventennale
  • Libri
  • Contatti
Menu
  • Argomenti
    • Programmazione & Linguaggi
      • Java
      • DataBase & elaborazione dei dati
      • Frameworks & Tools
      • Processi di sviluppo
    • Architetture dei sistemi
      • Sicurezza informatica
      • DevOps
    • Project Management
      • Organizzazione aziendale
      • HR
      • Soft skills
    • Lean/Agile
      • Scrum
      • Teoria della complessità
      • Apprendimento & Serious Gaming
    • Internet & Digital
      • Cultura & Società
      • Conferenze & Reportage
      • Marketing & eCommerce
    • Hardware & Tecnologia
      • Intelligenza artificiale
      • UX design & Grafica
  • Ultimo numero
  • Archivio
    • Archivio dal 2006 ad oggi
    • Il primo sito web – 1996-2005
  • Chi siamo
  • Ventennale
  • Libri
  • Contatti
Cerca
Chiudi

Nel numero:

101 novembre
, anno 2005

Oggetti persistenti con Hibernate

Un approccio alla persistenza puramente a oggetti

Avatar

Leonardo Casini

MokaByte

Oggetti persistenti con Hibernate

Un approccio alla persistenza puramente a oggetti

Leonardo Casini

Leonardo Casini

  • Questo articolo parla di: DataBase & elaborazione dei dati, Programmazione & Linguaggi

Hibernate è un motore di persistenza utilizzato per lo più per realizzare il mapping di tabelle preesistenti in forma di oggetti. In questo articolo vedremo come realizzare la persistenza di un modello ad oggetti puro, completamente separato dal database e dal modello relazionale.

Introduzione

Oggigiorno è raro trovare un‘applicazione che non abbia bisogno di immagazzinare dati persistenti in qualche modo, su file nei casi più semplici fino ad arrivare ai più sofisticati Database Management Systems (DBMS). Quando si scrivono applicazioni con database ci si trova di fronte a due possibili scenari: uno in cui il database esiste già  (legacy) e uno in cui va progettato da zero. Nel primo caso si può procedere con un reverse engineering per identificare un modello dei dati a partire dalle tabelle esistenti. Nel secondo caso l‘approccio tradizionale consiste nell‘identificare entità  e relazioni coinvolte e creare le tabelle sul database. In entrambi i casi si parte dalla definizione dei dati e vi si costruisce sopra l‘applicazione. Questo approccio, indubbiamente immediato quando si usano strumenti di sviluppo RAD (Rapid Application Development), diviene immediatamente svantaggioso con metodologie di sviluppo più sofisticate, in quanto vincola le entità  del modello dati (tipicamente ad oggetti con un linguaggio come Java) alla struttura relazionale tipica dei tradizionali database. I due modelli, quello relazionale e quello ad oggetti, sono fortemente diversi per cui è necessario escogitare una forma di “traduzione” da un modello all‘altro, detta Object/Relational Mapping (ORM). Questa traduzione è sempre necessaria ed introduce uno strato aggiuntivo di logica, con tutto ciò che ne consegue in termini di sviluppo, debugging, manutenzione. Inoltre l‘applicazione conserverà  inevitabilmente la natura relazionale del modello di partenza, risultando strutturata prevalentemente su tale modello piuttosto che sul paradigma di sviluppo ad oggetti, con lo sviluppatore sempre costretto a fare i conti con una traduzione più o meno esplicita da un modello all‘altro.

Persistenza con Hibernate

Esistono diversi strumenti per agevolare lo sviluppo di applicazioni con dati persistenti, strumenti che variano da piattaforma a piattaforma. Uno dei più diffusi è il motore di persistenza Hibernate. Supponendo di lavorare con la metodologia appena descritta, avremo sostanzialmente tre fasi di progettazione: 1. definizione del modello dati relazionale, 2. definizione del modello ad oggetti e 3. definizione del mapping fra l‘uno e l‘altro. In questo scenario, una volta progettato il modello relazionale dei dati, Hibernate può prendersi carico di tradurlo e mapparlo in oggetti, rendendo trasparente il processo. Partendo da un database legacy Hibernate è in grado di mappare le tabelle in classi: ogni riga della tabella sarà  un‘istanza della classe corrispondente. Lo sviluppatore non dovrà  più occuparsi di interagire con il DBMS per mezzo di JDBC, ma userà  la più familiare forma degli oggetti e le comuni strutture dati del linguaggio.

/* usando JDBC */ResultSet rs = stmt.executeQuery("SELECT * FROM TABELLA");while (rs.next()) {String s = rs.getString("CAMPO1");float n = rs.getFloat("CAMPO2");System.out.println(s + "   " + n);}/* con Hibernate */List righe = session.createQuery("from Tabella").list();for (Iterator i = righe.iterator(); i.hasNext();) {Tabella riga = (Tabella) i.next();System.out.println(riga.getCampo1 + "   " + riga.getCampo2);}

Ciò non deve però trarre in inganno. Nonostante l‘indubbio vantaggio di usare oggetti anzichà© statement SQL inviati tramite JDBC e l‘onere di gestire istanze di ResultSet, non ci troviamo di fronte ad un modello Object Oriented, bensì ad un modello relazionale in cui le tabelle appaiono in forma di oggetti: per lavorare con un modello realmente ad oggetti è sempre necessario introdurre un ulteriore strato di traduzione tra oggetti-tabella e oggetti-modello, con un costo sia in termini di tempo che in termini di codice da mantenere.

L‘approccio a Oggetti

Hibernate permette un approccio alla persistenza completamente diverso da quello tradizionale, un approccio totalmente orientato agli oggetti e trasparente allo sviluppatore. In un‘applicazione Java ben progettata troveremo tipicamente tre componenti distinte: un modello che rappresenta le entità  manipolate dall‘applicazione; alcune viste del modello, che presentano il modello all‘utente in una forma a lui leggibile; un controllore, che si occupa di gestire l‘input dell‘utente, esaudirne le richieste (delegando al modello ove necessario), interagire con il database e delegare alle viste la presentazione dei risultati. Esaminiamo dunque il modello, la componente che ci interessa in questa sede. Il modello è un‘astrazione delle entità  che la nostra applicazione deve gestire. Il paradigma ad oggetti permette una modellazione ricca e strutturata degli oggetti del mondo reale che dobbiamo rappresentare nell‘applicazione, fornendo costrutti come ereditarietà  e associazioni, pattern, ecc. non direttamente rappresentabili con un modello relazionale. In questa ottica risulta quindi più naturale progettare un modello puramente ad oggetti, direttamente implementabile in Java, e a partire da esso costruire il database. Hibernate permette di sviluppare questo approccio in modo diretto ed elegante, consentendo di concentrare gli sforzi esclusivamente sulla modellazione ad oggetti e gestendo tutte le problematiche di persistenza autonomamente ed in maniera del tutto trasparente. In questo modo è possibile progettare il modello e considerare questi oggetti come “persistenti”, dimenticandosi completamente dell‘esistenza del database!

Modellazione e metainformazioni

Supponiamo di dover gestire una semplice anagrafica di clienti, che possono essere sia persone che aziende. Ogni soggetto avrà  le sue informazioni anagrafiche e amministrative, oltre a vari indirizzi e numeri di telefono. Il modello potrebbe essere espresso come nel seguente diagramma:

Abbiamo il Soggetto, che può rappresentare appunto l‘astrazione del soggetto anagrafico ed incarnare il concetto di azienda; abbiamo poi una sua generalizzazione, Persona, che ne eredita attributi e comportamenti aggiungendone di nuovi; infine abbiamo la classe Indirizzo. Si possono notare alcune cose. Innanzitutto Soggetto possiede un attributo multivalore, numeroTelefono: un soggetto può avere da 0 a n numeri. Inoltre abbiamo modellato l‘associazione fra Soggetto ed Indirizzo come composizione, in quanto l‘indirizzo non può esistere se non associato ad un soggetto. Persona eredita da Soggetto ogni metodo e proprietà , comprese quindi la proprietà  numeriTelefono e la composizione con Indirizzo. Il vantaggio immediato di un simile modello è che può essere implementato direttamente in Java, inserendo normalmente tutti i metodi e gli attributi necessari.

/* listato Java del modello */public class Soggetto { private Long id; private String partitaIva; private String cognomeRagioneSociale; private Set indirizzi; private Set numeriTelefono;  /** Costruttore di default. */public Soggetto() {this(null);}/** Costruttore con id. */public Soggetto(final Long id) {this.id = id;indirizzi = new HashSet();numeriTelefono = new HashSet();}public Long getId() {return this.id;}public void setId(final Long id) {this.id = id;}public String getPartitaIva() {return this.partitaIva;}public void setPartitaIva(final String partitaIva) {this.partitaIva = partitaIva;}/** * Il cognome per una persona, la ragione sociale per un‘azienda, ecc. */public String getCognomeRagioneSociale() {return this.cognomeRagioneSociale;}public void setCognomeRagioneSociale(String name) {this.cognomeRagioneSociale = name;}public Set getIndirizzi() {return this.indirizzi;}public void setIndirizzi(final Set indirizzi) {this.indirizzi = indirizzi;}public Set getNumeriTelefono() {return this.numeriTelefono;}public void setNumeriTelefono(final Set numeri) {this.numeriTelefono = numeri;}public void addIndirizzo(final Indirizzo indirizzo) {indirizzi.add(indirizzo);}public void removeIndirizzo(final Indirizzo indirizzo) {indirizzi.remove(indirizzo);}public void addTelefono(final String telefono) {numeriTelefono.add(telefono);}public void removeTelefono(final String telefono) {numeriTelefono.remove(telefono);}}public class Persona extends Soggetto { private Date dataNascita; private String nomeProprio; private String genere;/** Costruttore di default. */public Persona() {super();}/** * La data di nascita. */public Date getDataNascita() {return this.dataNascita;}public void setDataNascita(final Date data) {this.dataNascita = data;}/** * Il nome proprio della persona. */public String getNomeProprio() {return this.nomeProprio;}public void setNomeProprio(final String nome) {this.nomeProprio = nome;}/** * Il genere, volgarmente detto sesso, che sarà  "M" per il genere * maschile ed "F" per quello femminile. */public String getGenere() {return this.genere;}public void setGenere(final String genere) {this.genere = genere;}}public class Indirizzo { private String indirizzo; private String comune; private String localita; private String nome; private String provincia; private String cap;/** Costruttore di default. */public Indirizzo() {indirizzo = null;comune = null;localita = null;nome = null;provincia = null;cap = null;}/** * Restituisce l‘indirizzo, p.es. "via Roma, 23". */public String getIndirizzo() {return this.indirizzo;}

/** * Imposta l‘indirizzo, p.es. "via Roma, 23". */public void setIndirizzo(final String indirizzo) {this.indirizzo = indirizzo;}/** * Il comune. */public String getComune() {return this.comune;}public void setComune(final String comune) {this.comune = comune;}/** * La località . */public String getLocalita() {return this.localita;}public void setLocalita(final String localita) {this.localita = localita;}/** * Nome identificativo per l‘indirizzo, p.es "abitazione", "ufficio", ecc. */public String getNome() {return this.nome;}public void setNome(final String nome) {this.nome = nome;}/** * La provincia. */public String getProvincia() {return this.provincia;}public void setProvincia(final String provincia) {this.provincia = provincia;}/** * Il CAP (Codice Avviamento Postale). */public String getCap() {return this.cap;}public void setCap(final String cap) {this.cap = cap;}}

Abbiamo quindi tre classi, ognuna con i suoi attributi privati e i suoi metodi accessori. In particolare abbiamo aggiunto a Soggetto dei metodi per aggiungere ed eliminare facilmente indirizzi e numeri di telefono (add/removeIndirizzo(), ecc.). Sarebbe possibile aggiungere ulteriori metodi e controlli (che abbiamo omesso per brevità ), per esempio un metodo per calcolare l‘età  di una persona in base alla data di nascita, o un controllo sulla correttezza del codice fiscale nel metodo setCodiceFiscale(). così com‘è abbiamo quindi un buon modello ad oggetti, funzionale alla nostra applicazione e facilmente gestibile dallo sviluppatore, ma non ancora persistente. Per renderlo tale dobbiamo fornire ad Hibernate le informazioni necessarie per poterlo gestire in modo appropriato. Per fare ciò abbiamo due strade: scrivere esplicitamente dei file XML contenenti le informazioni di mapping oppure fornire queste informazioni direttamente nei sorgenti del modello e lasciare che Hibernate generi questi file al posto nostro. Il secondo approccio è preferibile in quanto libera dall‘onere di scrivere esplicitamente file di configurazione aggiuntivi: avremo così un solo sorgente che implementa direttamente un modello persistente.

XDoclet è lo strumento che ci permette di inserire le informazioni di persistenza direttamente nei sorgenti. XDoclet mette a disposizione alcuni tag, interpretabili da Hibernate, da inserire nei commenti Javadoc (documentate i vostri sorgenti, vero?): questi tag, trovandosi nei commenti, vengono ignorati dal compilatore Java, ma sono visti e utilizzati profiquamente dagli stumenti di Hibernate. Questi tag permettono di definire quali classi e quali attributi dell‘oggetto devono essere immagazzinati in un database e come. I sorgenti così corredati sono quindi processati dagli strumenti di Hibernate, i quali si preoccupano di creare automaticamente lo schema del database e i file di mapping. Aggiungiamo ai nostri sorgenti i tag XDoclet.

/* sorgenti con xdoclet *//** * Soggetto. *  * @hibernate.class */public class Soggetto { private Long id; private String partitaIva; private String cognomeRagioneSociale; private Set indirizzi; private Set numeriTelefono;  /** Costruttore di default. */public Soggetto() {this(null);}/** Costruttore con id. */public Soggetto(final Long id) {this.id = id;indirizzi = new HashSet();numeriTelefono = new HashSet();}/** * @hibernate.id *  generator-class="native" */public Long getId() {return this.id;}public void setId(final Long id) {this.id = id;}/** * @hibernate.property *  length="16" *  unique="true" */public String getPartitaIva() {return this.partitaIva;}public void setPartitaIva(final String partitaIva) {this.partitaIva = partitaIva;}/** * Il cognome per una persona, la ragione sociale per un‘azienda, ecc. *  * @hibernate.property length="60" */public String getCognomeRagioneSociale() {return this.cognomeRagioneSociale;}public void setCognomeRagioneSociale(String name) {this.cognomeRagioneSociale = name;}/** * @hibernate.set * name="indirizzi" * @hibernate.collection-key *  column="id" * @hibernate.collection-composite-element *  class="articolo.Address" */public Set getIndirizzi() {return this.indirizzi;}public void setIndirizzi(final Set indirizzi) {this.indirizzi = indirizzi;}/** * @hibernate.set *  table="numeri_telefono" * @hibernate.collection-key *  column="id" * @hibernate.collection-element *  column="telefono" *  type="string" *  not-null="true" */public Set getNumeriTelefono() {return this.numeriTelefono;}public void setNumeriTelefono(final Set numeri) {this.numeriTelefono = numeri;}public void addIndirizzo(final Indirizzo indirizzo) {indirizzi.add(indirizzo);}public void removeIndirizzo(final Indirizzo indirizzo) {indirizzi.remove(indirizzo);}public void addTelefono(final String telefono) {numeriTelefono.add(telefono);}public void removeTelefono(final String telefono) {numeriTelefono.remove(telefono);}}/** * Persona. *  * @hibernate.joined-subclass * @hibernate.joined-subclass-key *  column="id" */public class Persona extends Soggetto { private Date dataNascita; private String nomeProprio; private String genere;/** Costruttore di default. */public Persona() {super();}/** * La data di nascita. *  * @hibernate.property */public Date getDataNascita() {return this.dataNascita;}public void setDataNascita(final Date data) {this.dataNascita = data;}/** * Il nome proprio della persona. *  * @hibernate.property *  length="30" */public String getNomeProprio() {return this.nomeProprio;}public void setNomeProprio(final String nome) {this.nomeProprio = nome;}/** * Il genere, volgarmente detto sesso, che sarà  "M" per il genere maschile ed "F" per quello * femminile. *  * @hibernate.property *  length="1" */public String getGenere() {return this.genere;}public void setGenere(final String genere) {this.genere = genere;}}/** * Indirizzo. */public class Indirizzo { private String indirizzo; private String comune; private String localita; private String nome; private String provincia; private String cap;/** Costruttore di default. */public Indirizzo() {indirizzo = null;comune = null;localita = null;nome = null;provincia = null;cap = null;}   /** * Restituisce l‘indirizzo, p.es. "via Roma, 23". * @return Una stringa contenente la via, la piazza, ecc. *  * @hibernate.property *  length="255" */public String getIndirizzo() {return this.indirizzo;}/** * Imposta l‘indirizzo, p.es. "via Roma, 23". * @param indirizzo Una stringa contenente la via, la piazza, ecc. */public void setIndirizzo(final String indirizzo) {this.indirizzo = indirizzo;}/** * Il comune. *  * @hibernate.property *  length="60" */public String getComune() {return this.comune;}public void setComune(final String comune) {this.comune = comune;}/** * La località . *  * @hibernate.property *  length="255" */public String getLocalita() {return this.localita;}public void setLocalita(final String localita) {this.localita = localita;}/** * Nome identificativo per l‘indirizzo, p.es "abitazione", "ufficio", ecc. *  * @hibernate.property *  length="30" *  not-null="true" */public String getNome() {return this.nome;}public void setNome(final String nome) {this.nome = nome;}/** * La provincia. *  * @hibernate.property *  length="60" */public String getProvincia() {return this.provincia;}public void setProvincia(final String provincia) {this.provincia = provincia;}/** * Il CAP (Codice Avviamento Postale). *  * @hibernate.property *  length="5" */public String getCap() {return this.cap;}public void setCap(final String cap) {this.cap = cap;}}

Quello che abbiamo fatto è di dire ad Hibernate quali sono le entità  e le proprietà  che devono essere rese persistenti. Il tag @hibernate.class che abbiamo inserito nella Javadoc della classe Soggetto dice che vogliamo farne una classe persistente. Il tag @hibernate.id per getId() segnala che la proprietà  rappresenta la chiave dell‘entità  ed il parametro generator-class=”native” chiede di usare una chiave autogenerata dal DBMS. Per tutte le altre proprietà  semplici non facciamo altro che dire con @hibernate.property che vogliamo una proprietà  persistente, in alcuni casi indicando la lunghezza del campo nel database. Hibernate, salvo diversamente indicato, determina il tipo e crea un attributo sul database con lo stesso nome della proprietà . Le proprietà  più interessanti sono quelle che riguardano indirizzi e numeri di telefono.

/** * @hibernate.set *  name="indirizzi" * @hibernate.collection-key *  column="id" * @hibernate.collection-composite-element *  class="Indirizzo" */public Set getIndirizzi() {return this.indirizzi;}

Con @hibernate.set specifichiamo che la proprietà  Indirizzi è appunto un insieme, sul quale definiamo la chiave id. Inoltre, con @hibernate.collection-composite-element, specifichiamo anche che la proprietà  Indirizzi è una composizione di oggetti di classe Indirizzo. poiché nel nostro modello la classe Indirizzo non rappresenta un‘entità  con esistenza propria bensì un attributo composto di Soggetto, omettiamo nella stringa Javadoc della classe Indirizzo il tag @hibernate.class, ma specifichiamo comunque le proprietà  persistenti. Per i numeri di telefono abbiamo una specifica analoga, con la sola differenza che l‘attributo numeriTelefono è multivalore, ma semplice, per cui possiamo definire l‘elemento in loco con @hibernate.collection-element fornendo il nome della colonna ed il tipo. L‘ultima notazione d‘interesse è quella per la classe Persona.

/** * @hibernate.joined-subclass * @hibernate.joined-subclass-key *  column="id" */public class Persona extends Soggetto {

poiché Persona estende Soggetto, ereditandone proprietà  e comportamenti, vogliamo che per la persistenza avvenga una cosa analoga. Per questo motivo segnaliamo ad Hibernate che la tabella Persona venga messa in join con la tabella Soggetto, ottenendo così l‘effetto desiderato. Infatti nel database avremo una situazione di questo tipo

Soggetto(id, partitaIva, nome)Persona(id, dataNascita, codiceFiscale, cognome, sesso)

dove ogni istanza di Persona corrisponderà  un‘istanza di Soggetto con uguale id. Il nostro lavoro per quanto riguarda lo sviluppo del modello e della sua persistenza finisce qui. Ci resta solo il compito di creare uno script di Ant che generi lo schema del database e i file di mapping per noi. Prima però vediamo come utilizzare il nostro modello persistente una volta messo in piedi.

Usare il modello

La prima cosa da fare è inizializzare il motore di Hibernate e aprire le strutture necessarie.

SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();Session session = sessionFactory.openSession();Transaction tx = session.beginTransaction();

Aggiungiamo una nuova persona:

Persona p = new Persona();p.setNome("Rocco");p.setCognome("Smitelson");p.setCodiceFiscale("SMTRCC66L31H501P");p.setSesso("M");// data di nascitaDate data = null;try {data = new SimpleDateFormat("dd/MM/yyyy").parse("31/10/1966");} catch (ParseException e) {System.out.println("Non è stato possibile fare il parsing della data.");}p.setDataNascita(data);// recapiti telefonicip.addTelefono("06123456789");p.addTelefono("34700112233");// indirizzoIndirizzo indirizzo = new Indirizzo();indirizzo.setRiferimento("abitazione");indirizzo.setIndirizzo("via della Paura, 90");indirizzo.setCap("00100");indirizzo.setLocalita("Pomezia");indirizzo.setProvincia("RM");indirizzo.setComune("Roma");p.addIndirizzo(indirizzo);

Come si può vedere lavoriamo sul modello senza consapevolezza della presenza di un database, utilizzando in tutto e per tutto Java e le sue strutture. La presenza del meccanismo di persistenza si avverte solo quando si decide di salvare l‘oggetto appena creato:

session.save(p);tx.commit();

Tutto qui. Hibernate si occupa di tradurre il nostro modello ad oggetti in quello relazionale in modo del tutto trasparente.

Generazione con Ant

Come dicevamo, Hibernate ha bisogno di un file di configurazione che indichi i parametri di accesso al database e gli schemi di mapping da utilizzare.

  com.mysql.jdbc.Driverjdbc:mysql://localhost/testutentepasswordorg.hibernate.dialect.MySQLDialecttrue

Abbiamo indicato come risorsa di mapping il file Soggetto.hbm.xml. Questo file ancora non esiste, ma verrà  generato automaticamente dallo script che stiamo per scrivere. Il pacchetto XDoclet fornisce un task di Ant per la generazione dei file di mapping a partire dai sorgenti, opportunamente arricchiti come abbiamo visto in precedenza. Allo stesso modo la libreria di Hibernate contiene un task di Ant per generare lo schema del database a partire dai file di mapping. Quello che occorre quindi è uno script build.xml di Ant configurato con gli opportuni classpath che lanci i task sui nostri sorgenti.

E‘ sufficiente scrivere lo script di Ant una volta per tutte, modificando soltanto le locazioni dei sorgenti e le directory di output caso per caso. Nel nostro esempio abbiamo i sorgenti in src/, i file di configurazione (come hibernate.cfg.xml) in src/conf/ e lo script build.xml in setup/. Lanciando lo script troveremo nella directory src/conf/ il file di mapping (con lo stesso path della classe mappata) ed in setup/ lo script SQL per generare lo schema del database. Se abbiamo fornito dei parametri di accesso al DBMS con i privilegi di scrittura troveremo lo schema già  presente nel database!

Conclusioni

Hibernate è un motore di persistenza alquanto potente, che può agire in modi diversi, a seconda del momento in cui interviene nello sviluppo. Se si progetta un modello dati completamente ad oggetti Hibernate rende il meccanismo di persistenza del tutto trasparente, permettendo allo sviluppatore di interagire con un modello realmente ad oggetti anzichà© con tabelle o oggetti-tabella, realizzando così un‘astrazione completa della base dati.

Riferimenti

Manuale Hibernate, paragrafo 6.4.1
http://www.hibernate.org/hib_docs/v3/reference/en/html/mapping.html#mapping-xdoclet

Progetto XDoclet
http://xdoclet.sourceforge.net

Facebook
Twitter
LinkedIn
Avatar

Leonardo Casini

Leonardo Casini

Leonardo Casini

Tutti gli articoli
Nello stesso numero
Loading...

Java Business Integration

Parte II: Component Framework e Service Engine

Gestione delle risorse all‘interno degli application server

Evitare comportamenti difficilmente tracciabili

Integration Patterns

Parte II

Applicazioni Desktop

Finestre delle preferenze

Controllo a distanza

Governare un‘applicazione usando i comandi batch

La Reflection in Java

Parte I: una buona conoscenza dei tipi parametrici

Service Oriented Architecture

Parte II: metodologia

Process Oriented Development: il processo alla base dello sviluppo

Parte II: aproccio diverso ai requisiti business

Java diventa nativo, grazie a Red Hat

Il supporto di Java su Linux

Nella stessa serie
Loading...

Digital revolution: trasformare le aziende in ecosistemi digitali

III parte: Dagli obiettivi strategici alle iniziative operative

Digital revolution: La teoria

Tema 2: Il framework OKR

Digital revolution: trasformare le aziende in ecosistemi digitali

II parte: Un workshop per definire la vision

Bitcoin, blockchain e criptovaluta

V parte: Come funziona Bitcoin. Transazioni e UTXO

Digital revolution: La teoria

Tema 1: Approccio Scrum-like alle trasformazioni organizzative

Digital revolution: trasformare le aziende in ecosistemi digitali

I parte: Primo incontro.

Bitcoin, blockchain e criptovaluta

IV parte: Come funziona Bitcoin. Chiavi, indirizzi e wallet

Che cosa significa fare una trasformazione agile?

II parte: Le buone pratiche

Bitcoin, blockchain e criptovaluta

III parte: Come funziona Bitcoin. Rete e crittografia

Che cosa significa fare una trasformazione agile?

I parte: Le indispensabili premesse

Oltre Google Maps?

Una nuova alleanza per le mappe digitali

“Babbo… Ma te che lavoro fai?”

Come spiegare a un bambino (e alla sua maestra) il mestiere dell'agile coach

Bitcoin, blockchain e criptovaluta

II parte: Perché è nato Bitcoin

Microservizi: non solo tecnologia

Quanto influiscono sul business?

LEGO® Serious Play®

Che cosa è il metodo LSP?

State of Agile 2022

Qualche considerazione sul 16° rapporto

Bitcoin, blockchain e criptovaluta

I parte: Breve storia del denaro

Stili di leadership per l’agilità

Oltre il comando e controllo

Effetto Forrester e dinamiche dei sistemi di produzione

La storiella di una birra per comprendere il Lean

Fare “il tagliando” a Scrum

A due anni dalla pubblicazione della nuova guida

Veicoli elettrici ed esperienza utente

II parte: Riflessioni su app e UX

OKR, cadenze in Kanban e Flight Levels

Uscire dalla trappola dell’agilità locale

Continuous Delivery per il proprio team di sviluppo

Principi e pratiche

Il contratto è agile!

Gli elementi del contratto e l'Agilità

Mokabyte

MokaByte è una rivista online nata nel 1996, dedicata alla comunità degli sviluppatori java.
La rivista tratta di vari argomenti, tra cui architetture enterprise e integrazione, metodologie di sviluppo lean/agile e aspetti sociali e culturali del web.

Imola Informatica

MokaByte è un marchio registrato da:
Imola Informatica S.P.A.
Via Selice 66/a 40026 Imola (BO)
C.F. e Iscriz. Registro imprese BO 03351570373
P.I. 00614381200
Cap. Soc. euro 100.000,00 i.v.

Privacy | Cookie Policy

Contatti

Contattaci tramite la nostra pagina contatti, oppure scrivendo a redazione@mokabyte.it

Seguici sui social

Facebook Linkedin Rss
Imola Informatica
Mokabyte