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 .
GO TO FULL VERSION