5.1 Varie forme di comunicazione uno a uno

C'è un altro caso interessante e piuttosto specifico di una relazione tra due classi Entity: una relazione uno a uno.

Chiamo questo caso molto specifico, poiché riguarda più gli oggetti Java che un database. Nel database, ci sono solo due opzioni per la relazione tra le tabelle:

  • La riga della tabella contiene un collegamento all'id di un'altra tabella.
  • La tabella dei servizi viene utilizzata per le relazioni molti-a-molti.

Nel caso delle classi di entità, potrebbero esserci opzioni descritte da diverse annotazioni:

  • @Incorporato
  • OneToOne unilaterale
  • OneToOne bilaterale
  • @MapsId

Di seguito considereremo il più popolare di loro.

5.2 Incorporato

A proposito, abbiamo già considerato l' opzione di comunicazione uno a uno@Embedded più semplice: questa è un'annotazione . In questo caso, abbiamo due classi memorizzate nella stessa tabella nel database.

Supponiamo di voler memorizzare l'indirizzo dell'utente nella classe UserAddress :


@Embeddable
class UserAddress {
   @Column(name="user_address_country")
   public String country;
   @Column(name="user_address_city")
   public String city;
   @Column(name="user_address_street")
   public String street;
   @Column(name="user_address_home")
   public String home;
}

Quindi dobbiamo solo aggiungere un campo con questo indirizzo alla classe User :


@Entity
@Table(name="user")
class User {
   @Column(name="id")
   public Integer id;
 
   @Embedded
   public UserAddress address;
 
   @Column(name="created_date")
   public Date createdDate;
}

Hibernate farà il resto: i dati verranno archiviati in una tabella, ma quando si scrivono query HQL, sarà necessario operare sui campi di classe.

Esempio di query HQL:

select from User where address.city = 'Paris'

5.3 OneToOne unilaterale

Immagina ora la situazione: abbiamo una tabella di origine dipendente e un'attività che fa riferimento a dipendente. Ma sappiamo per certo che è possibile assegnare al massimo un'attività a un utente. Poi possiamo usare l'annotazione per descrivere questa situazione @OneToOne.

Esempio:


@Entity
@Table(name="task")
class EmployeeTask {
   @Column(name="id")
   public Integer id;
 
   @Column(name="name")
   public String description;
 
   @OneToOne
   @JoinColumn(name = "employee_id")
   public Employee employee;
 
   @Column(name="deadline")
   public Date deadline;
}

Hibernate farà in modo che non solo un'attività abbia un utente, ma anche che un utente abbia una sola attività. Altrimenti, questo caso non è praticamente diverso da @ManyToOne.

5.4 OneToOne bilaterale

L'opzione precedente può essere un po' scomoda, perché spesso si desidera assegnare un dipendente non solo a un'attività, ma anche assegnare un'attività a un dipendente.

Per fare ciò, puoi aggiungere il campo EmployeeTask alla classe Employee e assegnargli le annotazioni corrette.


@Entity
@Table(name="employee")
class Employee {
   @Column(name="id")
   public Integer id;
 
   @OneToOne(cascade = CascadeType.ALL, mappedBy="employee")
   private EmployeeTask task;
}

Importante!La tabella dei dipendenti non ha un campo task_id , invece il campo employee_id della tabella delle attività viene utilizzato per stabilire una relazione tra le tabelle .

Stabilire una connessione tra oggetti è simile a questo:


Employee director = session.find(Employee.class, 4);
EmployeeTask task = session.find(EmployeeTask.class, 101);
task.employee = director;
director.task = task;
 
session.update(task);
session.flush();

Per rimuovere il collegamento, è necessario rimuovere anche i collegamenti da entrambi gli oggetti:


Employee director = session.find(Employee.class, 4);
EmployeeTask task = director.task;
 
task.employee = null;
session.update(task);
 
director.task = null;
session.update(director);
 
session.flush();