Mapim enum

Вече разбрахме How да картографираме примитивни типове данни: използваме анотацията @Column и анотацията @Type . Но не всички случаи могат да бъдат обхванати от тези анотации. И най-често срещаният случай е enum .

Java enum обектите могат да се съхраняват в базата данни по два начина:

  • като число
  • като низ

Нека напишем малък пример, където потребителят ще има любим цвят, който се задава с помощта на enum.


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

И добавете цветно поле към потребителския клас :


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

Ако искаме Hibernate да запази типа цвят в основата като числа , тогава имаме нужда от полетолюбим цвятдобавете анотация:


@Enumerated(EnumType.ORDINAL)

Ако искаме стойностите да се съхраняват като низове , тогава трябва да добавим анотация:


@Enumerated(EnumType.STRING)

Пример:


@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

Вторият полезен сценарий е картографиране на булев тип. Исторически се случи така, че SQL няма собствен тип данни за Boolean и instead of това там се използва всичко.

Трите най-често срещани опции са:

  • 1 or 0
  • „F“ or „T“
  • „Да“ or „Н“

Като цяло, ако ще проектирате вашата база, тогава е по-добре да напишете типа BIT веднага. Е, пълното картографиране за него ще изглежда така:


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

Е, ако не проектирате базата данни, вижте tableта по-горе и помислете How да картографирате правилно типовете, от които се нуждаете.

Изчисляеми полета

Понякога броят на полетата в клас Entity и броят на колоните в table не съвпадат. Може да има няколко причини за това.

Най-често срещаният е, когато има няHowво поле в нашия клас Entity, което не искаме да запазим в базата данни. С това всичко е ясно - просто добавете анотацията @Transient към такова поле и Hibernate ще го игнорира, когато работи с базата данни.

Пример:


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

Това е добра опция, но при четене на обект от базата данни, общото поле ще бъде нула. И бихме искали да съдържа произведението от ширина*височина. Това може да се направи и в Hibernate. За това има специална анотация @Formula .


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

Такова поле няма да бъде запазено в базата данни и когато обектът бъде прочетен от базата данни, стойността, изчислена по формулата, ще бъде записана в него.

SQL заявката ще изглежда така:

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

@Вграден

Друга полезна анотация е @Embedded . Тя ви позволява да разглеждате полетата на дъщерния обект като полета на самия клас Entity.

Да приемем, че имате потребителски клас и решите да добавите address към него:


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

Всичко изглежда наред, но от гледна точка на Java би било логично addressът да се постави в отделен клас. Адресът все още е отделна единица. Но How да направите това, ако цялата тази информация се съхранява в базата данни в потребителската table?

Анотацията @Embedded ще ни помогне . Първо ще създадем класа UserAddress и ще поставим цялата информация за address на потребителя в него:


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

След това използваме поле от този клас в нашия потребителски клас :


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

Благодарение на анотацията @Embedded , в момента на запазване на обекта, Hibernate ще разбере, че полетата на класа UserAddress трябва да се третират като полета на самия клас User .

важно! Ако решите да добавите две полета UserAddress към вашия потребителски клас , тогава използването на @Embedded вече няма да работи: ще имате дублиращи се полета и ще трябва да ги разделите по няHowъв начин. Това се прави чрез замяна на анотациите: с помощта на анотацията @AttributeOverrides .

Искам да знаете това, но няма да навлизаме в подробности тук. Мисля, че това е достатъчно, за да си счупиш главата. За любопитните мога да оставя линк към официалната documentация .