Mapim opsomming

We hebben al bedacht hoe we primitieve gegevenstypen in kaart kunnen brengen: we gebruiken de @Column- annotatie en de @Type- annotatie . Maar niet alle gevallen kunnen door deze annotaties worden gedekt. En het meest voorkomende geval is enum .

Java-enum-objecten kunnen op twee manieren in de database worden opgeslagen:

  • als een nummer
  • als een snaar

Laten we een klein voorbeeld schrijven waarin de gebruiker een favoriete kleur heeft, die wordt ingesteld met enum.


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

En voeg een kleurveld toe aan de klasse 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;
}

Als we willen dat Hibernate het kleurtype als getallen in de basis opslaat , hebben we het veld nodigfavoriete kleurannotatie toevoegen:


@Enumerated(EnumType.ORDINAL)

Als we willen dat de waarden als strings worden opgeslagen , moeten we een annotatie toevoegen:


@Enumerated(EnumType.STRING)

Voorbeeld:


@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-booleaanse waarde

Het tweede bruikbare scenario is booleaanse typetoewijzing. Het is historisch zo gebeurd dat SQL geen eigen gegevenstype voor Boolean heeft en dat in plaats daarvan alles wordt gebruikt.

De drie meest voorkomende opties zijn:

  • 1 of 0
  • 'F' of 'T'
  • 'J' of 'N'

Als u uw basis gaat ontwerpen, is het in het algemeen beter om meteen het BIT-type te schrijven. Welnu, de volledige mapping ervoor ziet er als volgt uit:


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

Welnu, als u de database niet aan het ontwerpen bent, bekijk dan de bovenstaande tabel en bedenk hoe u de typen die u nodig hebt correct kunt toewijzen.

Berekende velden

Soms komen het aantal velden in een Entity-klasse en het aantal kolommen in een tabel niet overeen. Hiervoor kunnen verschillende redenen zijn.

De meest voorkomende is wanneer er een veld in onze Entity-klasse is dat we niet willen opslaan in de database. Hiermee is alles duidelijk - voeg gewoon de @Transient- annotatie toe aan zo'n veld en Hibernate zal het negeren bij het werken met de database.

Voorbeeld:


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

Dit is een goede optie, maar bij het lezen van een object uit de database zal het totale veld null zijn. En we willen dat het het product van breedte*hoogte bevat. Dit kan ook in Hibernate. Hiervoor is een speciale @Formula- annotatie .


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

Zo'n veld wordt niet in de database opgeslagen en wanneer het object uit de database wordt gelezen, wordt de door de formule berekende waarde ernaar geschreven.

De SQL-query ziet er ongeveer zo uit:

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

@Ingebed

Een andere handige annotatie is @Embedded . Hiermee kunt u de velden van het onderliggende object beschouwen als velden van de klasse Entity zelf.

Stel dat u een gebruikersklasse hebt en u besluit er een adres aan toe te voegen:


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

Alles lijkt in orde, maar vanuit het oogpunt van Java zou het logisch zijn om het adres in een aparte klasse te plaatsen. Het adres is nog steeds een aparte entiteit. Maar hoe doe je dit als al deze informatie is opgeslagen in de database in de gebruikerstabel?

De @Embedded annotatie zal ons helpen . Eerst maken we de klasse UserAddress en plaatsen we alle informatie over het adres van de gebruiker erin:


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

En dan gebruiken we een veld van deze klasse in onze gebruikersklasse :


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

Dankzij de @Embedded- annotatie begrijpt Hibernate op het moment dat het object wordt opgeslagen dat de velden van de klasse UserAddress moeten worden behandeld als velden van de klasse User zelf .

Belangrijk! Als u besluit om twee UserAddress- velden aan uw User- klasse toe te voegen , werkt het gebruik van @Embedded niet meer: ​​u krijgt dubbele velden en u zult ze op de een of andere manier moeten scheiden. Dit wordt gedaan door annotaties te overschrijven: met behulp van de @AttributeOverrides annotatie .

Ik wil dat je dit weet, maar we zullen hier niet in detail treden. Ik denk dat dit genoeg is om je hoofd te breken. Voor de nieuwsgierigen kan ik een link naar de officiële documentatie achterlaten .