Mapim enumerazione

Abbiamo già capito come mappare i tipi di dati primitivi: usiamo l' annotazione @Column e l' annotazione @Type . Ma non tutti i casi possono essere coperti da queste annotazioni. E il caso più comune è enum .

Gli oggetti enum Java possono essere archiviati nel database in due modi:

  • come numero
  • come una stringa

Scriviamo un piccolo esempio in cui l'utente avrà un colore preferito, che viene impostato utilizzando enum.


enum Color {
   RED,
   ORANGE,
   YELLOW,
   GREEN,
   BLUE,
   VIOLET
}

E aggiungi un campo color alla classe User :


@Entity
@Table(name="user")
class User
{
   @Column(name="id")
   public Integer id;
 
   @Column(name="favorite_color")
   public Color favoriteColor;
 
   @Column(name="created_date")
   public Date createdDate;
}

Se vogliamo che Hibernate salvi il tipo Color nella base come numeri , allora abbiamo bisogno del campocolore preferitoaggiungi annotazione:


@Enumerated(EnumType.ORDINAL)

Se vogliamo che i valori vengano memorizzati come stringhe , dobbiamo aggiungere un'annotazione:


@Enumerated(EnumType.STRING)

Esempio:


@Entity
@Table(name="user")
class User
{
   @Column(name="id")
   public Integer id;
 
   @Enumerated(EnumType.ORDINAL) //value will be saved to the base as a number
   @Column(name="favorite_color")
   public Color favoriteColor;
 
   @Column(name="created_date")
   public Date createdDate;
}

Mapim booleano

Il secondo scenario utile è la mappatura dei tipi booleani. È successo così storicamente che SQL non ha un proprio tipo di dati per Boolean e invece viene utilizzato qualsiasi cosa.

Le tre opzioni più comuni sono:

  • 1 o 0
  • 'F' o 'T'
  • 'Y' o 'N'

In generale, se hai intenzione di progettare la tua base, è meglio scrivere subito il tipo BIT. Bene, la mappatura completa sarà simile a questa:


	@Column(name = "is_correct", columnDefinition = "BIT")
	@Type(type = "org.hibernate.type.NumericBooleanType")
    private Boolean isCorrect;

Bene, se non stai progettando il database, guarda la tabella sopra e pensa a come mappare correttamente i tipi di cui hai bisogno.

Campi calcolati

A volte il numero di campi in una classe Entity e il numero di colonne in una tabella non corrispondono. Ci possono essere diverse ragioni per questo.

Il più comune è quando c'è un campo nella nostra classe Entity che non vogliamo salvare nel database. Tutto è chiaro con questo: basta aggiungere l' annotazione @Transient a tale campo e Hibernate lo ignorerà quando si lavora con il database.

Esempio:


@Entity(name = "Square")
public class Square {
           	@Id
           	public Long id;
 
           	public Integer width;
 
           	public Integer height;
 
           	@Transient
           	public Integer total;
}

Questa è una buona opzione, ma quando si legge un oggetto dal database, il campo totale sarà nullo. E vorremmo che contenesse il prodotto di larghezza*altezza. Questo può essere fatto anche in ibernazione. C'è una speciale annotazione @Formula per questo .


@Entity(name = "Square")
public class Square {
           	@Id
           	public Long id;
 
           	public Integer width;
 
           	public Integer height;
 
           	@Formula(value = " width * height ")
          	public Integer total;
}

Tale campo non verrà salvato nel database e quando l'oggetto viene letto dal database, il valore calcolato dalla formula verrà scritto su di esso.

La query SQL sarà simile a questa:

 SELECT id, width, height, (width* height) AS total FROM Square;

@Incorporato

Un'altra annotazione utile è @Embedded . Permette di considerare i campi dell'oggetto figlio come campi della classe Entity stessa.

Diciamo che hai una classe utente e decidi di aggiungere un indirizzo ad essa:


@Entity
@Table(name="user")
class User
{
   @Column(name="id")
    public Integer id;
 
   @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;
 
   @Column(name="created_date")
    public Date createdDate;
}

Tutto sembra andare bene, ma dal punto di vista di Java sarebbe logico inserire l'indirizzo in una classe separata. L'indirizzo è ancora un'entità separata. Ma come farlo se tutte queste informazioni sono memorizzate nel database nella tabella utente?

L'annotazione @Embedded ci aiuterà . Per prima cosa, creeremo la classe UserAddress e vi inseriremo tutte le informazioni sull'indirizzo dell'utente:


@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;
}

E poi usiamo un campo di questa classe nella nostra 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;
}

Grazie all'annotazione @Embedded , al momento del salvataggio dell'oggetto, Hibernate capirà che i campi della classe UserAddress devono essere trattati come campi della classe User stessa .

Importante! Se decidi di aggiungere due campi UserAddress alla tua classe User , l'utilizzo di @Embedded non funzionerà più: avrai campi duplicati e dovrai separarli in qualche modo. Questo viene fatto sovrascrivendo le annotazioni: usando l' annotazione @AttributeOverrides .

Voglio che tu lo sappia, ma non entreremo nei dettagli qui. Penso che questo sia abbastanza per farti rompere la testa. Per i curiosi, posso lasciare un link alla documentazione ufficiale .