CodeGym /Cursos /All lectures for PT purposes /Cenários úteis de mapeamento de dados

Cenários úteis de mapeamento de dados

All lectures for PT purposes
Nível 1, Lição 222
Disponível

Mapim enum

Já descobrimos como mapear tipos de dados primitivos: usamos a anotação @Column e a anotação @Type . Mas nem todos os casos podem ser cobertos por essas anotações. E o caso mais comum é enum .

Os objetos Java enum podem ser armazenados no banco de dados de duas maneiras:

  • como um número
  • como uma corda

Vamos escrever um pequeno exemplo onde o usuário terá uma cor favorita, que é definida usando enum.


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

E adicione um campo de cor à 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;
}

Se quisermos que o Hibernate salve o tipo Color na base como números , então precisamos do campocor favoritaadicionar anotação:


@Enumerated(EnumType.ORDINAL)

Se quisermos que os valores sejam armazenados como strings , precisamos adicionar uma anotação:


@Enumerated(EnumType.STRING)

Exemplo:


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

O segundo cenário útil é o mapeamento de tipo booleano. Aconteceu historicamente que o SQL não tem seu próprio tipo de dados para Boolean e qualquer coisa é usada lá.

As três opções mais comuns são:

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

Em geral, se você for projetar sua base, é melhor escrever o tipo BIT imediatamente. Bem, o mapeamento completo para ele ficará assim:


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

Bem, se você não está projetando o banco de dados, consulte a tabela acima e pense em como mapear corretamente os tipos que você precisa.

Campos calculados

Às vezes, o número de campos em uma classe Entity e o número de colunas em uma tabela não correspondem. Pode haver várias razões para isso.

O mais comum é quando existe algum campo em nossa classe Entity que não queremos salvar no banco de dados. Tudo fica claro com isso - basta adicionar a anotação @Transient a esse campo e o Hibernate irá ignorá-lo ao trabalhar com o banco de dados.

Exemplo:


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

Esta é uma boa opção, mas ao ler um objeto do banco de dados, o campo total será nulo. E gostaríamos que contivesse o produto largura x altura. Isso também pode ser feito no Hibernate. Existe uma anotação @Formula especial para isso .


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

Esse campo não será salvo no banco de dados e, quando o objeto for lido do banco de dados, o valor calculado pela fórmula será gravado nele.

A consulta SQL ficará mais ou menos assim:

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

@Integrado

Outra anotação útil é @Embedded . Permite considerar os campos do objeto filho como campos da própria classe Entity.

Digamos que você tenha uma classe User e decida adicionar um endereço a ela:


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

Tudo parece estar bem, mas do ponto de vista do Java, seria lógico colocar o endereço em uma classe separada. O endereço ainda é uma entidade separada. Mas como fazer isso se todas essas informações estão armazenadas no banco de dados na tabela do usuário?

A anotação @Embedded nos ajudará . Primeiro, criaremos a classe UserAddress e colocaremos todas as informações do endereço do usuário nela:


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

E então usamos um campo desta classe em nossa 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;
}

Graças à anotação @Embedded , no momento de salvar o objeto, o Hibernate entenderá que os campos da classe UserAddress precisam ser tratados como campos da própria classe User .

Importante! Se você decidir adicionar dois campos UserAddress à sua classe User , usar @Embedded não funcionará mais: você terá campos duplicados e precisará separá-los de alguma forma. Isso é feito substituindo as anotações: usando a anotação @AttributeOverrides .

Eu quero que você saiba disso, mas não vamos entrar em detalhes aqui. Acho que isso é o suficiente para você quebrar a cabeça. Para os curiosos, posso deixar um link para a documentação oficial .

Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION