Mapim enum
Vi har redan listat ut hur man mappar primitiva datatyper: vi använder @Column- kommentaren och @Type -kommentaren . Men inte alla fall kan täckas av dessa anteckningar. Och det vanligaste fallet är enum .
Java enum-objekt kan lagras i databasen på två sätt:
- som ett nummer
- som ett snöre
Låt oss skriva ett litet exempel där användaren kommer att ha en favoritfärg, som ställs in med hjälp av enum.
enum Color {
RED,
ORANGE,
YELLOW,
GREEN,
BLUE,
VIOLET
}
Och lägg till ett färgfält i användarklassen :
@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;
}
Om vi vill att Hibernate ska spara färgtypen till basen som siffror behöver vi fältetfavoritfärglägg till anteckning:
@Enumerated(EnumType.ORDINAL)
Om vi vill att värdena ska lagras som strängar måste vi lägga till en anteckning:
@Enumerated(EnumType.STRING)
Exempel:
@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
Det andra användbara scenariot är kartläggning av boolesk typ. Det hände bara historiskt att SQL inte har en egen datatyp för Boolean och allt används där istället.
De tre vanligaste alternativen är:
- 1 eller 0
- "F" eller "T"
- "Y" eller "N"
I allmänhet, om du ska designa din bas, så är det bättre att skriva BIT-typen direkt. Tja, den fullständiga kartläggningen för det kommer att se ut så här:
@Column(name = "is_correct", columnDefinition = "BIT")
@Type(type = "org.hibernate.type.NumericBooleanType")
private Boolean isCorrect;
Tja, om du inte designar databasen, se tabellen ovan och fundera över hur du korrekt kartlägger de typer du behöver.
Beräknade fält
Ibland stämmer inte antalet fält i en Entity-klass och antalet kolumner i en tabell. Det kan finnas flera anledningar till detta.
Det vanligaste är när det finns något fält i vår Entity-klass som vi inte vill spara i databasen. Allt är klart med detta - lägg bara till @Transient -anteckningen i ett sådant fält så ignorerar Hibernate det när du arbetar med databasen.
Exempel:
@Entity(name = "Square")
public class Square {
@Id
public Long id;
public Integer width;
public Integer height;
@Transient
public Integer total;
}
Detta är ett bra alternativ, men när du läser ett objekt från databasen blir det totala fältet null. Och vi skulle vilja att den innehåller produkten av bredd*höjd. Detta kan också göras i Hibernate. Det finns en speciell @Formula- anteckning för detta .
@Entity(name = "Square")
public class Square {
@Id
public Long id;
public Integer width;
public Integer height;
@Formula(value = " width * height ")
public Integer total;
}
Ett sådant fält kommer inte att sparas i databasen, och när objektet läses från databasen kommer värdet som beräknas med formeln att skrivas till det.
SQL-frågan kommer att se ut ungefär så här:
SELECT id, width, height, (width* height) AS total FROM Square;
@Inbäddad
En annan användbar anteckning är @Embedded . Det låter dig betrakta fälten i det underordnade objektet som fält i själva klassen Entity.
Låt oss säga att du har en användarklass och du bestämmer dig för att lägga till en adress till den:
@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;
}
Allt verkar vara bra, men ur Javas synvinkel vore det logiskt att lägga adressen i en separat klass. Adressen är fortfarande en separat enhet. Men hur gör man detta om all denna information är lagrad i databasen i användartabellen?
@Embedded -kommentaren hjälper oss . Först skapar vi klassen UserAddress och lägger in all information om användarens adress i den:
@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;
}
Och sedan använder vi ett fält av den här klassen i vår användarklass :
@Entity
@Table(name="user")
class User
{
@Column(name="id")
public Integer id;
@Embedded
public UserAddress address;
@Column(name="created_date")
public Date createdDate;
}
Tack vare @Embedded- kommentaren kommer Hibernate att förstå att fälten i klassen UserAddress måste behandlas som fält för själva klassen Användar när objektet sparas .
Viktig! Om du bestämmer dig för att lägga till två UserAddress- fält till din användarklass , kommer det inte längre att fungera att använda @Embedded : du kommer att ha dubbletter av fält och du måste separera dem på något sätt. Detta görs genom att åsidosätta kommentarer: med @AttributeOverrides -kommentaren .
Jag vill att du ska veta detta, men vi går inte in på detaljer här. Jag tror att det här är tillräckligt för att du ska krossa huvudet. För den nyfikna kan jag lämna en länk till den officiella dokumentationen .
GO TO FULL VERSION