Mapim enumerare

Ne-am dat deja seama cum să mapam tipurile de date primitive: folosim adnotarea @Column și adnotarea @Type . Dar nu toate cazurile pot fi acoperite de aceste adnotări. Și cel mai frecvent caz este enum .

Obiectele Java enumerare pot fi stocate în baza de date în două moduri:

  • ca număr
  • ca o sfoară

Să scriem un mic exemplu în care utilizatorul va avea o culoare preferată, care este setată folosind enum.


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

Și adăugați un câmp de culoare la clasa 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;
}

Dacă vrem ca Hibernate să salveze tipul de culoare la bază ca numere , atunci avem nevoie de câmpulCuloare preferataadauga adnotare:


@Enumerated(EnumType.ORDINAL)

Dacă dorim ca valorile să fie stocate ca șiruri de caractere , atunci trebuie să adăugăm o adnotare:


@Enumerated(EnumType.STRING)

Exemplu:


@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 Boolean

Al doilea scenariu util este maparea de tip boolean. Din punct de vedere istoric, s-a întâmplat ca SQL să nu aibă propriul tip de date pentru boolean și în schimb se folosește orice.

Cele mai comune trei opțiuni sunt:

  • 1 sau 0
  • 'Fort'
  • „Y” sau „N”

În general, dacă aveți de gând să vă proiectați baza, atunci este mai bine să scrieți imediat tipul BIT. Ei bine, maparea completă pentru aceasta va arăta astfel:


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

Ei bine, dacă nu proiectați baza de date, atunci consultați tabelul de mai sus și gândiți-vă cum să mapați corect tipurile de care aveți nevoie.

Câmpuri calculate

Uneori, numărul de câmpuri dintr-o clasă Entitate și numărul de coloane dintr-un tabel nu se potrivesc. Pot exista mai multe motive pentru aceasta.

Cel mai frecvent este atunci când există un câmp în clasa noastră Entitate pe care nu dorim să-l salvăm în baza de date. Totul este clar cu asta - trebuie doar să adăugați adnotarea @Transient la un astfel de câmp și Hibernate o va ignora atunci când lucrați cu baza de date.

Exemplu:


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

Aceasta este o opțiune bună, dar când citiți un obiect din baza de date, câmpul total va fi nul. Și ne-am dori să conțină produsul lățime*înălțime. Acest lucru se poate face și în Hibernate. Există o adnotare specială @Formula pentru aceasta .


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

Un astfel de câmp nu va fi salvat în baza de date, iar atunci când obiectul este citit din baza de date, valoarea calculată prin formulă va fi scrisă în el.

Interogarea SQL va arăta cam așa:

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

@Încorporat

O altă adnotare utilă este @Embedded . Vă permite să considerați câmpurile obiectului copil drept câmpuri ale clasei Entity în sine.

Să presupunem că aveți o clasă de utilizator și vă decideți să adăugați o adresă la aceasta:


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

Totul pare să fie bine, dar din punctul de vedere al Java, ar fi logic să punem adresa într-o clasă separată. Adresa este încă o entitate separată. Dar cum se face asta dacă toate aceste informații sunt stocate în baza de date în tabelul de utilizatori?

Adnotarea @Embedded ne va ajuta . Mai întâi, vom crea clasa UserAddress și vom pune toate informațiile despre adresa utilizatorului în ea:


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

Și apoi folosim un câmp din această clasă în clasa noastră de utilizator :


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

Datorită adnotării @Embedded , în momentul salvării obiectului, Hibernate va înțelege că câmpurile clasei UserAddress trebuie tratate ca câmpuri ale clasei User în sine .

Important! Dacă decideți să adăugați două câmpuri UserAddress la clasa dvs. de utilizator , atunci folosirea @Embedded nu va mai funcționa: veți avea câmpuri duplicat și va trebui să le separați cumva. Acest lucru se face prin suprascrierea adnotărilor: folosind adnotarea @AttributeOverrides .

Vreau să știți asta, dar nu vom intra în detalii aici. Cred că asta este suficient pentru a-ți sparge capul. Pentru cei curioși, pot lăsa un link către documentația oficială .