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
  • 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

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

Picture of 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

Avatar
Leonardo Casini
Facebook
Twitter
LinkedIn
Picture of Leonardo Casini

Leonardo Casini

Tutti gli articoli
Nello stesso numero
Loading...

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

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

Nella stessa serie
Loading...

Accessibilità in team di prodotto: sfide, normative e best practice

I parte: Cosa è l’accessibilità e perché implementarla

Il web al tempo della GEO (Generative Engine Optimization)

II parte: Strategie per strutturare i contenuti

Un backlog non tanto buono

II parte: Caratteristiche e ruolo del backlog.

FIWARE: Open APIs for Open Minds

V parte: Implementazione del sistema di ricarica

Il web al tempo della GEO (Generative Engine Optimization)

I parte: Struttura e ricerca delle informazioni

Un backlog non tanto buono

I parte: Un progetto con qualche difficoltà

DDD, microservizi e architetture evolutive: uno sguardo d’insieme

X parte: Il ruolo del Software Architect

FIWARE: Open APIs for Open Minds

IV parte: Sistema di ricarica intelligente per veicoli elettrici

Tra Play14 e serious gaming

Un ponte tra gioco e apprendimento

DDD, microservizi e architetture evolutive: uno sguardo d’insieme

IX parte: Event Sourcing is not Event Streaming

FIWARE: Open APIs for Open Minds

III parte: Tecnologie e implementazione

Agilità organizzativa

II parte: Qualche caso d’esempio

Agilità organizzativa

I parte: Individui e interazioni nelle aziende moderne

FIWARE: Open APIs for Open Minds

II parte: Generic Enablers per costruire ecosistemi smart

Intelligenza artificiale e industria

Riflessioni sull’uomo e sulla macchina

Effetto Forrester e dinamiche dei sistemi di produzione

La storiella di una birra per comprendere il Lean

DDD, microservizi e architetture evolutive: uno sguardo d’insieme

VIII parte: La filosofia dell’architettura del software

Digital revolution: trasformare le aziende in ecosistemi digitali

XVIII parte: Una piattaforma comune a tutti gli eventi

Scene dalla “neolingua”

Panoramica semiseria dell’incomunicabilità aziendale

Autenticazione schede elettorali… lean!

Simulazione lean nella gestione di un seggio

FIWARE: Open APIs for Open Minds

I parte: Fondamenti e architettura

Italian Agile Days: una conferenza matura

Resoconto da IAD24 di Firenze

“Sì, ma quanto mi costi?”. Considerazioni sull’Agile in azienda

III parte: Earned Value Analisys e Scrum

La lezione da apprendere? Le organizzazioni che apprendono

IV parte: Gli archetipi sistemici

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