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!