O
JPA 2.1 trouxe conversores que nos permitem especificar como mapear tipos de
dados. Um conversor deve implementar a interface javax.persistence.AttributeConverter<X,Y>, passando a classe
da entidade em X e classe do banco de dados em Y. O conversor também precisa
ser anotado com javax.persistence.Converter.
Ao
implementar essa interface, dois métodos são requeridos: o convertToDatabaseCollumn que é usado pelo JPA para persistir o
atributo no banco de dados e o convertToEntityAtribute
que é usado para trazer os dados do banco para o Java.
Os
conversores funcionam basicamente como os conversores do JSF, e podem ser usados
de 2 maneiras, com o atributo autoApplay=true na anotação @Converter, fazendo
com que o conversor seja aplicado automaticamente em todos os casos, ou
aplicando o conversor diretamente na propriedade nas entidades - @Convert(Converter = NomeDaClasse.class) – conforme necessidade.
Podem ser usados para mapear
novos tipo de dados que o JPA ainda não mapeia sozinho como é o caso do LocalDate e LocalDateTime, mapear Enums, quando se quer por exemplo,
guardar um atributo do enum ao invés da sua representação ORDINAL ou STRING e até para criptografia, como vou
mostrar em um outro post.
Como exemplo vou me deter ao converter para o LocalDate e
um converter para guardar uma propriedade de um Enum. Vamos ao primeiro
exemplo:
@Entity
public class Pedido {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", updatable = false, nullable = false)
private Long id;
@Column
private LocalDate dataPrevisaoEntrega;
...
}
Segue o conversor:
@Converter(autoApply = true)
public class LocalDateConverter implements AttributeConverter<LocalDate, Date> {
@Override
public Date convertToDatabaseColumn(LocalDate localDate) {
return (localDate == null ? null : Date.valueOf(localDate));
}
@Override
public LocalDate convertToEntityAttribute(Date sqlDate) {
return (sqlDate == null ? null : sqlDate.toLocalDate());
}
}
Perceba que no exemplo, na anotação @Converter foi passado
o atributo autoApplay=true. Isso faz com que o conversor seja aplicado
automaticamente em todos os casos. Quando esse atributo é falso, você fica
responsável por informar ao JPA sempre que desejar usá-lo, anotando a
propriedade com @Convert e passando a classe do conversor como segue:
@Column
@Convert(Converter = LocalDateConverter.class)
private LocalDate
dataPrevisaoEntrega;
Vamos para o segundo exemplo, onde temos o Enum, o
Converter e como aplicá-lo:
public enum Veiculo {
BUS("B"), CAR("C"), TRAIN("T"), PLANE("P");
private String codigo;
private Veiculo(String codigo) {
this.codigo = codigo;
}
public String getCodigo()
{
return codigo;
}
public static Veiculo fromCodigo(String codigo) {
switch (codigo) {
case "B":
return Veiculo.BUS;
case "C":
return Veiculo.CAR;
case "T":
return Veiculo.TRAIN;
case "P":
return Veiculo.PLANE;
default:
throw new IllegalArgumentException("codigo
[" + codigo
+ "] não suportado.");
}
}
}
O converter para o Enum segue abaixo:
@Converter(autoApply = true)
public class VeiculoConverter implements AttributeConverter<Veiculo, String> {
@Override
public String convertToDatabaseColumn(Veiculo Veiculo) {
return Veiculo.getCodigo();
}
@Override
public Veiculo convertToEntityAttribute(String dbData) {
return Veiculo.fromCodigo(dbData);
}
}
E então basta usar o enum:
@Entity
public class Viagem
{
private Veiculo veiculo;
...
}
Pronto, sempre que precisarmos especificar como uma classe
deve ser salva no banco podemos usar os conversores. Vou compartilhar um site
muito bom para quem quer se aprofundar no JPA e no qual me baseei para este
artigo:
Nenhum comentário:
Postar um comentário