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 .
GO TO FULL VERSION