Énumération Mapim

Nous avons déjà compris comment mapper les types de données primitifs : nous utilisons l' annotation @Column et l' annotation @Type . Mais tous les cas ne peuvent pas être couverts par ces annotations. Et le cas le plus courant est enum .

Les objets Java enum peuvent être stockés dans la base de données de deux manières :

  • en tant que nombre
  • comme une chaîne

Écrivons un petit exemple où l'utilisateur aura une couleur préférée, qui est définie à l'aide de enum.


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

Et ajoutez un champ de couleur à la 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;
}

Si nous voulons qu'Hibernate enregistre le type de couleur dans la base sous forme de nombres , nous avons besoin du champcouleur préféréeajouter une annotation :


@Enumerated(EnumType.ORDINAL)

Si nous voulons que les valeurs soient stockées sous forme de chaînes , nous devons ajouter une annotation :


@Enumerated(EnumType.STRING)

Exemple:


@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 booléen

Le deuxième scénario utile est le mappage de type booléen. Il se trouve qu'historiquement, SQL n'a pas son propre type de données pour Boolean et que tout y est utilisé à la place.

Les trois options les plus courantes sont :

  • 1 ou 0
  • 'F' ou 'T'
  • 'O' ou 'N'

En général, si vous allez concevoir votre base, il est préférable d'écrire le type BIT tout de suite. Eh bien, le mappage complet ressemblera à ceci :


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

Eh bien, si vous ne concevez pas la base de données, consultez le tableau ci-dessus et réfléchissez à la manière de mapper correctement les types dont vous avez besoin.

Champs calculés

Parfois, le nombre de champs dans une classe Entity et le nombre de colonnes dans une table ne correspondent pas. Il peut y avoir plusieurs raisons à cela.

Le plus courant est lorsqu'il y a un champ dans notre classe Entity que nous ne voulons pas enregistrer dans la base de données. Tout est clair avec cela - ajoutez simplement l' annotation @Transient à un tel champ et Hibernate l'ignorera lors de l'utilisation de la base de données.

Exemple:


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

C'est une bonne option, mais lors de la lecture d'un objet à partir de la base de données, le champ total sera nul. Et nous voudrions qu'il contienne le produit largeur * hauteur. Cela peut également être fait dans Hibernate. Il existe une annotation spéciale @Formula pour cela .


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

Un tel champ ne sera pas enregistré dans la base de données et lorsque l'objet sera lu à partir de la base de données, la valeur calculée par la formule y sera écrite.

La requête SQL ressemblera à ceci :

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

@Embarqué

Une autre annotation utile est @Embedded . Il permet de considérer les champs de l'objet enfant comme des champs de la classe Entity elle-même.

Supposons que vous ayez une classe User et que vous décidiez d'y ajouter une adresse :


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

Tout semble aller bien, mais du point de vue de Java, il serait logique de mettre l'adresse dans une classe à part. L'adresse est toujours une entité distincte. Mais comment faire si toutes ces informations sont stockées dans la base de données dans la table utilisateur ?

L'annotation @Embedded nous aidera . Premièrement, nous allons créer la classe UserAddress et y mettre toutes les informations sur l'adresse de l'utilisateur :


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

Et puis on utilise un champ de cette classe dans notre 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;
}

Grâce à l' annotation @Embedded , au moment de la sauvegarde de l'objet, Hibernate comprendra que les champs de la classe UserAddress doivent être traités comme des champs de la classe User elle-même .

Important! Si vous décidez d'ajouter deux champs UserAddress à votre classe User , l'utilisation de @Embedded ne fonctionnera plus : vous aurez des champs en double et vous devrez les séparer d'une manière ou d'une autre. Cela se fait en remplaçant les annotations : en utilisant l' annotation @AttributeOverrides .

Je veux que vous le sachiez, mais nous n'entrerons pas dans les détails ici. Je pense que c'est assez pour vous casser la tête. Pour les curieux, je peux laisser un lien vers la documentation officielle .