martedì 29 luglio 2014

Hibernate relazione molti-a-molti

Vai all'indice

Una relazione molti-a-molti esiste quando un singolo record in una tabella può essere correlato a molti record in una seconda, e un singolo record nella seconda a molti record nella prima tabella.
Per questo esempio utilizzerò le tabelle utente e applicazione definite nel primo post, da notare che esiste una terza tabella utente_applicazione che mette in collegamento le altre due. Ogni utente può essere collegato a più applicazioni ed ogni applicazione può essere utilizzata da più utenti.



Di seguito modifico l'entità Utente.java dell'esempio precedente per la gestione della relazione molti-a-molti e definisco la nuova entità Applicazione.java.

package jar;

import java.sql.Date;
import java.util.HashSet; 
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.ManyToOne;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.JoinTable;
import javax.persistence.JoinColumns;
import javax.persistence.JoinColumn;
import javax.persistence.Table;

@Entity
@Table(name="utente")
public class Utente {

   @Id
   @GeneratedValue
   @Column(name="userid")
   private int userId;
   
   @Column(name="nome")
   private String nome;
   
   @Column(name="cognome")
   private String cognome;
   
   @Column(name="ruolo")
   private String ruolo;
   
   @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "utente")
    @JoinColumn(name="userid")
   private Dettaglioutente dettaglioutente;
    
    @ManyToOne
    @JoinColumn(name="ufficioId", 
                insertable=false, updatable=false, 
                nullable=false)
    private Ufficio ufficio;
    
    @ManyToMany(fetch = FetchType.LAZY,cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @JoinTable(name="utente_applicazione", 
                joinColumns={@JoinColumn(name="userid")}, 
                inverseJoinColumns={@JoinColumn(name="appid")})
    private Set<Applicazione> applicazioni = new HashSet<Applicazione>();  

   
   public Utente() {
      
   }
   
   public Utente(String nome, String cognome, String ruolo) {
      this.nome = nome;
      this.cognome = cognome;
      this.ruolo = ruolo;
      
   }
   
   // Metodi Getter e Setter
   

   public Set<Applicazione> getApplicazioni() {
      return applicazioni;
   }

   public void setApplicazioni(Set<Applicazione> applicazioni) {
      this.applicazioni = applicazioni;
   }   

   public int getUserId() {
      return userId;
   }

   public void setUserId(int userId) {
      this.userId = userId;
   }


   public String getNome() {
      return nome;
   }

   public void setNome(String nome) {
      this.nome = nome;
   }

   public String getCognome() {
      return cognome;
   }

   public void setCognome(String cognome) {
      this.cognome = cognome;
   }

   public String getRuolo() {
      return ruolo;
   }

   public void setRuolo(String ruolo) {
      this.ruolo = ruolo;
   }

   public Dettaglioutente getDettaglioutente() {
      return dettaglioutente;
   }

   public void setDettaglioutente(Dettaglioutente dettaglioutente) {
      this.dettaglioutente = dettaglioutente;
   }
   
   public Ufficio getUfficio() {
      return ufficio;
   }

   public void setUfficio(Ufficio ufficio) {
      this.ufficio = ufficio;
   }   
}


package jar;

import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.FetchType;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

@Entity
@Table(name="applicazione")
public class Applicazione {

    @Id
    @Column(name="appid")
    @GeneratedValue
    private int appid;

    @Column(name="nomeapp")
    private String nomeapp;

    @Column(name="desrizioneapp")
    private String descrizioneapp;    
     
    @ManyToMany(fetch = FetchType.LAZY, mappedBy="applicazioni", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    private Set<Utente> utenti = new HashSet<Utente>();
    
   public Applicazione() {
      
   }

    public Applicazione(String nomeapp, String descrizioneapp) {
        this.nomeapp = nomeapp;
        this.descrizioneapp = descrizioneapp;
    }

   public int getAppid() {
      return appid;
   }

   public void setAppid(int appid) {
      this.appid = appid;
   }

   public String getNomeapp() {
      return nomeapp;
   }

   public void setNomeapp(String nomeapp) {
      this.nomeapp = nomeapp;
   }

   public String getDescrizioneapp() {
      return descrizioneapp;
   }

   public void setDescrizioneapp(String descrizioneapp) {
      this.descrizioneapp = descrizioneapp;
   }

   public Set<Utente> getUtenti() {
      return utenti;
   }

   public void setUtenti(Set<Utente> utenti) {
      this.utenti = utenti;
   }
   

}

L'annotazione @ManyToMany viene utilizzata per definire una relazione molti-a-molti tra le entità Utente e Applicazione. Ogni associazione molti-a-molti ha una parte proprietaria e una non proprietaria.
L’annotazione @JoinTable  si definisce sul lato proprietario di una relazione molti-a-molti e serve per indicare la tabella che registra le associazioni, che nel nostro caso è Utente_applicazione. Se l'associazione è bidirezionale, entrambe le parti possono essere definite proprietarie.
L’attributo name dell’annotazione @JoinTable specifica la tabella che memorizza i riferimenti alle primary key delle tabelle utente e applicazione.
Questa tabella contiene le colonne userid e appid che sono le chiavi esterne che fanno riferimento alle chiavi primarie delle due tabelle.
Gli elementi joinColumns e inverseJoinColumns fanno riferimento alle primary key; il primo descrive la parte proprietaria della relazione. L’annotazione @JoinColumn  viene utilizzata per definire la colonna di collegamento in entrambe le tabelle.
L’attributo mappedBy serve per indicare l’entità proprietaria della relazione nell’entità subordinata e viene usato esclusivamente nel caso di una relazione bidirezionale.
Il parametro cascade  comunica all’EntityManager come estendere un’operazione di persistenza su una particolare entità verso le entità a questa collegate.
Di default l’elemento cascade è vuoto e quindi le operazioni di persistenza non vengono diffuse.
I valori possono essere settati a ALL, MERGE, PERSIST, REFRESH, REMOVE.
Da notare che ho usato <SET> per mappare la tabella Applicazione su Utente e viceversa. <set> può memorizzare solo oggetti unici, ciò significa che elementi duplicati non possono essere contenuti in un set. Quando si aggiunge lo stesso elemento di un set per la seconda volta, andrà a sostituire quello già esistente. Il tipo corrispondente di un <set> in Java è java.util.Set.

Quindi modifico il file: /src/main/resources/hibernate.cfg.xml mappando jar.Applicazione:

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
<session-factory>
  <!-- DB connection settings -->
  <property name="connection.driver_class">org.apache.derby.jdbc.ClientDriver</property>
  <property name="connection.url">jdbc:derby://localhost:1527/derby/derbyDB</property>
  <property name="connection.username">tst</property>
  <property name="connection.password">test</property>

  <property name="connection.pool_size">1</property>
  <property name="dialect">org.hibernate.dialect.DerbyDialect</property>
  <property name="current_session_context_class">thread</property>
  <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
  <property name="show_sql">true</property>
  <property name="hbm2ddl.auto">validate</property>

  <mapping class="jar.Utente"/>
  <mapping class="jar.Dettaglioutente"/>
  <mapping class="jar.Ufficio"/>
  <mapping class="jar.Applicazione"/>

</session-factory>
</hibernate-configuration>

La classe HibernateUtil rimane invariata.
La classe Main.java esegue le operazioni di CRUD (Inserimento, lettura e cancellazione). E' possibile eseguire l'applicazione cliccando col tasto destro su questa classe, quindi selezionare Run as > Java Application. Il risultato dell'elaborazione è visibile nella scheda console di Eclipse.

package jar;

import java.sql.Date;
import java.util.List;
import java.util.ArrayList;
import java.util.Set;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.HibernateException;

public class Main {

   @SuppressWarnings("unchecked")
   public static void main(String[] args) {

      System.out.println("Hibernate Test");
      
      SessionFactory sf = HibernateUtil.getSessionFactory();

      int iduff = 0;
      
      // Inserimento
      Session session = sf.openSession();
      session.beginTransaction();   
      int delIdapp = 0; //definisco l'id dell'app. che cancellerò
      try {
           Applicazione app1 = new Applicazione("SAP", "Sistema gestionale");
           Applicazione app2 = new Applicazione("GIS", "Sistemi territoriali");
           session.save(app1);
           session.save(app2);
           delIdapp = app1.getAppid();

         Utente ute1 = new Utente("Franco", "Neri", "Utente");
         Utente ute2 = new Utente("Giovanni", "Bianchi", "Admin");   
               
         ute1.getApplicazioni().add(app1);
         ute1.getApplicazioni().add(app2);
         ute2.getApplicazioni().add(app1);
         ute2.getApplicazioni().add(app2);
         session.save(ute1);
         session.save(ute2);

         session.getTransaction().commit();
      }catch (HibernateException e) {
         session.getTransaction().rollback();
           e.printStackTrace();
      } finally {
         session.close();
      }
      
      Lista(); 

      // Cancello una applicazione e tutte le associazioni con gli utenti
      session = sf.openSession();
      session.beginTransaction();         
      try {   
          Applicazione appx = (Applicazione) session.load(Applicazione.class, delIdapp);
          List<Utente> utenti = session.createQuery("from Utente").list();
             for (Utente utex : utenti) {
                utex.getApplicazioni().remove(appx);
                session.save(utex);
             } 
             session.delete(appx);
         
         session.getTransaction().commit();   
      }catch (HibernateException e) {
         session.getTransaction().rollback();
           e.printStackTrace();
      } finally {
          session.close();
      }
       
       Lista();       

   }

   @SuppressWarnings("unchecked")
   public static void Lista() {
      Session session = HibernateUtil.getSessionFactory().openSession();
      session.beginTransaction();   
      System.out.println("Lista utenti ufficio");
      List<Utente> uts = session.createQuery("from Utente").list();
      for (Utente ut1 : uts) {
         System.out.println("Info utente " + ut1.getNome()  + " , "
            + ut1.getCognome() + ", "
            + ut1.getRuolo()); 
            for(Applicazione appy : ut1.getApplicazioni()) {
                    System.out.println("Nome applicazione associate all'utente " + appy.getNomeapp());
                }
              
      }
      session.close();
   }
}

Di seguito riporto tutti i moduli creati finora nel progetto.





Hai apprezzato questo post? Conferma le mie competenze o scrivi una segnalazione sul mio profilo Linkedin!

lunedì 21 luglio 2014

Hibernate relazione uno-a-molti

Vai all'indice

Questo post illustra come Hibernate gestisce la relazione uno-a-molti tra due tabelle. In questo tipo di relazione un record di una tabella è correlato a più record di una seconda tabella, ma i record della seconda tabella sono correlati a un solo record della prima. In questo specifico esempio, che riparte dall'applicazione creata nel post precedente, un utente (pensiamo ad un impiegato di un ufficio) può appartenere ad un solo ufficio, mentre ogni ufficio è formato da molti utenti. Le tabelle utilizzate sono Utente ed Ufficio già definite nel post introduttivo.

Di seguito modifico l'entità Utente.java dell'esempio precedente per la gestione dell'Ufficio e definisco una nuova entità Ufficio.java.

package jar;

import java.sql.Date;
import java.util.HashSet; 
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.ManyToOne;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.JoinTable;
import javax.persistence.JoinColumns;
import javax.persistence.JoinColumn;
import javax.persistence.Table;

@Entity
@Table(name="utente")
public class Utente {

  @Id
  @GeneratedValue
  @Column(name="userid")
  private int userId;
  
  @Column(name="nome")
  private String nome;
  
  @Column(name="cognome")
  private String cognome;
  
  @Column(name="ruolo")
  private String ruolo;
  
  @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "utente")
    @JoinColumn(name="userid")
  private Dettaglioutente dettaglioutente;
    
    @ManyToOne
    @JoinColumn(name="ufficioId", 
                insertable=false, updatable=false, 
                nullable=false)
    private Ufficio ufficio;
    
  public Utente() {  
  }
  
  public Utente(String nome, String cognome, String ruolo) {
    this.nome = nome;
    this.cognome = cognome;
    this.ruolo = ruolo;
    
  }
  
  // Metodi Getter e Setter

  public int getuserId() {
    return userId;
  }

  public void setuserId(int userId) {
    this.userId = userId;
  }

  public String getNome() {
    return nome;
  }

  public void setNome(String nome) {
    this.nome = nome;
  }

  public String getCognome() {
    return cognome;
  }

  public void setCognome(String cognome) {
    this.cognome = cognome;
  }

  public String getRuolo() {
    return ruolo;
  }

  public void setRuolo(String ruolo) {
    this.ruolo = ruolo;
  }

  public Dettaglioutente getDettaglioutente() {
    return dettaglioutente;
  }

  public void setDettaglioutente(Dettaglioutente dettaglioutente) {
    this.dettaglioutente = dettaglioutente;
  }
  
  public Ufficio getUfficio() {
    return ufficio;
  }

  public void setUfficio(Ufficio ufficio) {
    this.ufficio = ufficio;
  }
  
  
}


package jar;

import java.util.HashSet;
import java.util.List;


import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.CascadeType;
import javax.persistence.JoinColumn;

import org.hibernate.annotations.IndexColumn;

@Entity
@Table(name="UFFICIO")
public class Ufficio {

    @Id
    @GeneratedValue
    @Column(name="ufficioid")
    private int ufficioId;
     
    @Column(name="nomeufficio")
    private String nomeUfficio;
  
    @OneToMany(cascade={CascadeType.ALL})
    @JoinColumn(name="ufficioid")
    @IndexColumn(name="iduf")
    private Set<Utente> utenti = new HashSet<Utente>();
    
  public Ufficio() {
  }
    
    public Ufficio(String nome) {
    this.nomeUfficio = nome;
  }
    
  // Metodi Getter e Setter

  public int getUfficioId() {
    return ufficioId;
  }

  public void setUfficioId(int ufficioId) {
    this.ufficioId = ufficioId;
  }

  public String getNomeUfficio() {
    return nomeUfficio;
  }

  public void setNomeUfficio(String nomeUfficio) {
    this.nomeUfficio = nomeUfficio;
  }

  public Set<Utente> getUtenti() {
    return utenti;
  }

  public void setUtenti(Set<Utente> utenti) {
    this.utenti = utenti;
  }
    
}

L'annotazione @ManyToOne definisce l'associazione della classe Utente nella classe di entità Ufficio, viceversa per l'annotazione @OneToMany.
In questo caso specifico l’associazione è bidirezionale, quindi lato Ufficio sarà uno a molti (@OneToMany) mentre lato Utente molti a uno (@ManyToOne). Un'associazione bidirezionale consente la navigazione partendo da entrambe le entità.
In java si fa uso delle classi Set o List per mappare tra loro le entità.
L'annotazione @JoinColumn viene utilizzata per specificare quale colonna viene mappata per collegare le due entità.
La colonna IDUF, definita nella tabella utente, memorizza il valore dell'indice per mantenere l'ordine con cui gli utenti vengono mappati nell'ufficio.
E' importante menzionare l'annotazione fetch= FetchType.Lazy. Questa opzione assicura che gli oggetti figlio non vengano caricati a meno che non siano esplicitamente invocati dall'applicazione chiamando il metodo getUtente() sul padre, cioè sull'oggetto Ufficio. Al contrario specificando fetch= FetchType.Eager, Hibernate caricherà i figli quando sarà caricato il padre: quest'ultima opzione, nel caso di database più complessi con molte tabelle e relazioni,  comporta una sensibile riduzione delle performance.

Quindi modifico il file: /src/main/resources/hibernate.cfg.xml mappando Ufficio.jar:

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
<session-factory>
  <!-- DB connection settings -->
  <property name="connection.driver_class">org.apache.derby.jdbc.ClientDriver</property>
  <property name="connection.url">jdbc:derby://localhost:1527/derby/derbyDB</property>
  <property name="connection.username">tst</property>
  <property name="connection.password">test</property>

  <property name="connection.pool_size">1</property>
  <property name="dialect">org.hibernate.dialect.DerbyDialect</property>
  <property name="current_session_context_class">thread</property>
  <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
  <property name="show_sql">true</property>
  <property name="hbm2ddl.auto">validate</property>

  <mapping class="jar.Utente"/>
  <mapping class="jar.Dettaglioutente"/>
  <mapping class="jar.Ufficio"/>

</session-factory>
</hibernate-configuration>

La classe HibernateUtil rimane invariata.
La classe Main.java esegue le operazioni di CRUD (Inserimento, lettura e cancellazione). E' possibile eseguire l'applicazione cliccando col tasto destro su questa classe, quindi selezionare Run as > Java Application. Il risultato dell'elaborazione è visibile nella scheda console di Eclipse.

package jar;

import java.sql.Date;
import java.util.List;
import java.util.ArrayList;
import java.util.Set;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.HibernateException;

public class Main {

  @SuppressWarnings("unchecked")
  public static void main(String[] args) {

    System.out.println("Hibernate Test");
    
    SessionFactory sf = HibernateUtil.getSessionFactory();

    int iduff = 0;
    
    // Inserimento
    Session session = sf.openSession();
    session.beginTransaction();  
    try {
      Ufficio uff1 = new Ufficio();
      uff1.setNomeUfficio("Vendite");  
      Utente ute1 = new Utente("Franco", "Neri", "Utente");
      Utente ute2 = new Utente("Giovanni", "Bianchi", "Admin");      
          uff1.getUtenti().add(ute1);
          uff1.getUtenti().add(ute2);
        iduff = uff1.getUfficioId();
        session.save(uff1);  
        iduff = uff1.getUfficioId();
      session.getTransaction().commit();
    }catch (HibernateException e) {
      session.getTransaction().rollback();
      System.out.println("Anomalia su inserimento ");
          e.printStackTrace();
    } finally {
      session.close();
    }
    
    Lista(); 

    session = sf.openSession();
    session.beginTransaction();      
    try {  
      Ufficio uffx = (Ufficio) session.load(Ufficio.class, iduff);
      List<Utente> utes = session.createQuery("from Utente").list();
      for (Utente utex : utes) {
        uffx.getUtenti().remove(utex);
        session.delete(utex);
      }   
      session.delete(uffx);
      session.getTransaction().commit();  
    }catch (HibernateException e) {
      session.getTransaction().rollback();
      System.out.println("Anomalia su inserimento ");
          e.printStackTrace();
    } finally {
       session.close();
    }
     
     Lista();     

  }

  @SuppressWarnings("unchecked")
  public static void Lista() {
    Session session = HibernateUtil.getSessionFactory().openSession();
    session.beginTransaction();  
    System.out.println("Lista utenti ufficio");
    List<Utente> uts = session.createQuery("from Utente").list();
    for (Utente ut1 : uts) {
      System.out.println(ut1.getNome()  + " , "
        + ut1.getCognome() + ", "
        + ut1.getRuolo()+ ", " 
        + ut1.getUfficio().getNomeUfficio()
            );
    }
    session.close();
  }
}


Di seguito riporto l'alberatura del progetto.





Hai apprezzato questo post? Conferma le mie competenze o scrivi una segnalazione sul mio profilo Linkedin!

domenica 13 luglio 2014

Hibernate relazione uno-a-uno

Vai all'indice

Definito il progetto su Eclipse, il passo successivo è quello di creare il domain model, ovvero l'insieme delle entità del dominio e delle relazioni fra esse.
Le entità rappresentano i dati di un DB relazionale e una singola entità solitamente corrisponde alla struttura di una  tabella. 
Hibernate è un ORM acronimo di Object Relational Mapping, un metodo di programmazione per mappare gli oggetti al modello relazionale. Il mapping può essere di due tipi: tramite file XML o tramite le annotazioni. Io utilizzo le annotazioni, poiché rendono le operazioni di mapping più semplici e manutenibili rispetto ai file XML.
Come primo esempio prendo in considerazione le tabelle "utente" e "dettaglioutente"(descritte nel post precedente) che contengono i dati anagrafici degli utenti e tra loro hanno una relazione uno-a-uno. Una relazione uno-a-uno esiste quando un soggetto è legato con un'unica occorrenza all'altra entità, per cui esiste un'unica chiave primaria che lega entrambe le entità. Quindi ho creato le due classi: Utente.java e Dettaglioutente.java. In queste due classi la chiave comune è "userid" che è la chiave primaria della tabella Utente e rappresenta la relazione uno-a-uno con la tabella Dettaglioutente.

package jar;

import java.sql.Date;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.ManyToOne;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.JoinTable;
import javax.persistence.JoinColumns;
import javax.persistence.JoinColumn;
import javax.persistence.Table;

@Entity
@Table(name="utente")
public class Utente {

@Id
@GeneratedValue
@Column(name="userid")
private int userId;

@Column(name="nome")
private String nome;

@Column(name="cognome")
private String cognome;

@Column(name="ruolo")
private String ruolo;

@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "utente")
@JoinColumn(name="userid")
private Dettaglioutente dettaglioutente;


public Utente() {

}

public Utente(String nome, String cognome, String ruolo) {
  this.nome = nome;
  this.cognome = cognome;
this.ruolo = ruolo;

}

// Metodi Getter e Setter

public int getuserId() {
  return userId;
}

public void setuserId(int userId) {
  this.userId = userId;
}

public String getNome() {
  return nome;
}

public void setNome(String nome) {
  this.nome = nome;
}

public String getCognome() {
  return cognome;
}

public void setCognome(String cognome) {
  this.cognome = cognome;
}

public String getRuolo() {
  return ruolo;
}

public void setRuolo(String ruolo) {
  this.ruolo = ruolo;
}

public Dettaglioutente getDettaglioutente() {
  return dettaglioutente;
}

public void setDettaglioutente(Dettaglioutente dettaglioutente) {
  this.dettaglioutente = dettaglioutente;
}

}

package jar;

import java.sql.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
import javax.persistence.FetchType;

import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;


@Entity
@Table(name="dettaglioutente")
public class Dettaglioutente {

@Id
@Column(name="userid", unique=true, nullable=false)
@GeneratedValue(generator="gen")
@GenericGenerator(name="gen", strategy="foreign", parameters=@Parameter(name="property", value="utente"))
private int userId;

@Column(name="datanascita")
private Date dataNascita;

@Column(name="via")
private String via;

@Column(name="citta")
private String citta;

@Column(name="telefono")
private String telefono;

@OneToOne(fetch = FetchType.LAZY, optional=true)
@PrimaryKeyJoinColumn
@Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE})
private Utente utente;

public Dettaglioutente() {

}

public Dettaglioutente(Date dataNascita, String via, String citta, String telefono) {
  this.dataNascita = dataNascita;
  this.via = via;
  this.citta = citta;
  this.telefono = telefono;
}


// Metodi Getter e Setter

public int getUserId() {
  return userId;
}

public void setUserId(int userId) {
  this.userId = userId;
}

public Date getDataNascita() {
  return dataNascita;
}

public void setDataNascita(Date dataNascita) {
  this.dataNascita = dataNascita;
}

public String getVia() {
  return via;
}

public void setVia(String via) {
  this.via = via;
}

public String getCitta() {
  return citta;
}

public void setCitta(String citta) {
  this.citta = citta;
}

public String getTelefono() {
  return telefono;
}

public void setTelefono(String telefono) {
  this.telefono = telefono;
}

public Utente getUtente() {
  return utente;
}

public void setUtente(Utente utente) {
  this.utente = utente;
}

}

A questo punto ho inserito il file hibernate.cfg.xml che contiene tutti i parametri di collegamento e configurazione di Hibernate. Questo file va collocato nel percorso /src/main/resources folder, da notare che queste cartelle non sono presenti nell'attuale struttura di progetto.
Per creare questa alberatura clicco col tasto destro del mouse sul progetto > New > Source Folder > con il nome "/src/main/resources/" poi clicco Finish. A questo punto copio il file nella cartella appena creata in modo da ottenere: /src/main/resources/hibernate.cfg.xml

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
<session-factory>
  <!-- DB connection settings -->
  <property name="connection.driver_class">org.apache.derby.jdbc.ClientDriver</property>
  <property name="connection.url">jdbc:derby://localhost:1527/derby/derbyDB</property>
  <property name="connection.username">tst</property>
  <property name="connection.password">test</property>

  <property name="connection.pool_size">1</property>
  <property name="dialect">org.hibernate.dialect.DerbyDialect</property>
  <property name="current_session_context_class">thread</property>
  <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
  <property name="show_sql">true</property>
  <property name="hbm2ddl.auto">validate</property>

  <mapping class="jar.Utente"/>
  <mapping class="jar.Dettaglioutente"/>

</session-factory>
</hibernate-configuration>

Ora creo la classe HibernateUtil che mi aiuta a creare la SessionFactory dal file di configurazione di Hibernate. Il SessionFactory viene utilizzato per ottenere le istanze delle sessioni che rappresentano i singoli processi.

package jar;

import java.util.Properties; import org.hibernate.SessionFactory;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.hibernate.HibernateException;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistryBuilder;

public class HibernateUtil {

  
  private static SessionFactory sessionFactory = null;  
  private static ServiceRegistry serviceRegistry = null;

    public static SessionFactory getSessionFactory() {

      try {  
        Configuration configuration = new Configuration();  
        configuration.configure();  
        
        Properties properties = configuration.getProperties();
      
        serviceRegistry = new ServiceRegistryBuilder().applySettings(properties).buildServiceRegistry();          
        sessionFactory = configuration.buildSessionFactory(serviceRegistry);  
        } catch (Throwable ex) {
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
      
      return sessionFactory; 
    }
}


La classe Main.java esegue le operazioni di CRUD (Inserimento, lettura, aggiornamento e cancellazione). E' possibile mandare in esecuzione l'applicazione cliccando col tasto destro su questa classe, quindi selezionare Run as > Java Application. Il risultato dell'elaborazione è visibile nella scheda console di Eclipse.

package jar;

import java.sql.Date;
import java.util.List;
import java.util.Set;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.HibernateException;

public class Main {

  public static void main(String[] args) {

    System.out.println("Hibernate Test");

    SessionFactory sf = HibernateUtil.getSessionFactory();

    int indice; // indice su cui si vuole eseguire aggiornamento e cancellazione

    // Inserimento
    Session session = sf.openSession();
    session.beginTransaction();
    try {
      Dettaglioutente dettUte = new Dettaglioutente( new Date(821212), "via Roma 11", "Milano", "0612345678");
      Utente ute = new Utente("Mario", "Rossi", "Utente");
      ute.setDettaglioutente(dettUte);
      dettUte.setUtente(ute);
      session.save(ute);
      indice = ute.getUserid();
      session.getTransaction().commit();
    }catch (HibernateException e) {
      session.getTransaction().rollback();
      System.out.println("Anomalia su inserimento ");
      e.printStackTrace();
    } finally {
      session.close();
    }

    Lista();

    // Modifica
    Utente ut = null;
    session = sf.openSession();
    session.beginTransaction();
    try {
      ut = (Utente) session.get(Utente.class, indice);
      ut.setNome("Giovanni");
      ut.getDettaglioutente().setCitta("Firenze");
      session.getTransaction().commit();
    }catch (HibernateException e) {
      System.out.println("Anomalia su aggiornamento ");
      session.getTransaction().rollback();
      e.printStackTrace();
    } finally {
      session.close();
    }

    Lista();

    // Cancellazione
    session = sf.openSession();
    session.beginTransaction();
    try {
      ut = (Utente) session.get(Utente.class, indice);
      session.delete(ut);
      session.getTransaction().commit();
    }catch (HibernateException e) {
      System.out.println("Anomalia su cancellazione ");
      session.getTransaction().rollback();
      e.printStackTrace();
    } finally {
      session.close();
    }


    Lista();


  }

  @SuppressWarnings("unchecked")
  public static void Lista() {
    Session session = HibernateUtil.getSessionFactory().openSession();
    session.beginTransaction();
    List uts = session.createQuery("from Utente").list();
    for (Utente ut1 : uts) {
      System.out.println(ut1.getNome() + " , "
          + ut1.getCognome() + ", "
          + ut1.getRuolo()+ ", "
          + ut1.getDettaglioutente().getVia() + ", "
          + ut1.getDettaglioutente().getCitta() + ", "
          + ut1.getDettaglioutente().getTelefono() + ", "
          + ut1.getDettaglioutente().getDataNascita()
          );
    }
    session.close();
  }
}

Di seguito riporto l'alberatura del progetto.





Hai apprezzato questo post? Conferma le mie competenze o scrivi una segnalazione sul mio profilo Linkedin!