Tenho uma tabela MySQL que armazena informações sobre impressoras de etiquetas:
ip | porta | apelido |
---|---|---|
181012304 | 9100 | PRLMA213 |
181012370 | 9100 | PRLMA212 |
181012398 | 9100 | PRLMA211 |
181012559 | 9100 | PRLMA210 |
Há uma entidade JPA correspondente para esta tabela em meu aplicativo:
@Entity
@Table(name = "printers", catalog = "gage_requests")
public class PrinterEntity {
@Id
@Column(name = "ip")
@ColumnTransformer(read = "INET_NTOA(ip)", write = "INET_ATON(?)")
private String address;
private int port;
private String nickname;
public String getAddress() {
return this.address;
}
public int getPort() {
return this.port;
}
public String getNickname() {
return this.nickname;
}
}
Quando tento CriteriaQuery
recuperar a lista de impressoras, o endereço IP não é convertido corretamente e continua sendo um número inteiro:
public List<PrinterEntity> findPrinters() {
CriteriaBuilder criteriaBuilder = this.entityManager.getCriteriaBuilder();
CriteriaQuery<PrinterEntity> criteriaQuery = criteriaBuilder.createQuery(PrinterEntity.class);
Root<PrinterEntity> root = criteriaQuery.from(PrinterEntity.class);
criteriaQuery.select(root);
TypedQuery<PrinterEntity> query = this.entityManager.createQuery(criteriaQuery);
return query.getResultStream().peek(this.entityManager::detach)
.collect(Collectors.toCollection(LinkedList::new));
}
Lista retornada:
[
{
"address": "181012304",
"nickname": "PRLMA213",
"port": 9100
},
{
"address": "181012370",
"nickname": "PRLMA212",
"port": 9100
},
{
"address": "181012398",
"nickname": "PRLMA211",
"port": 9100
},
{
"address": "181012559",
"nickname": "PRLMA210",
"port": 9100
}
]
Quando hibernate.show_sql
definido como verdadeiro, o seguinte SQL é registrado:
select printerent0_.ip as ip1_5_, printerent0_.nickname as nickname2_5_, printerent0_.port as port3_5_ from gage_requests.printers printerent0_
Claramente está faltando a INET_NTOA
função usada na minha @ColumnTransformer
anotação, então parece que a anotação não está sendo aplicada.
Por que isso acontece?
@ColumnTransformer
não suportado em@Id
camposO Hibernate
@ColumnTransformer
pode não ser suportado para um campo de chave primária, conforme indicado pela anotação@Id
aqui.Isso foi rejeitado na solicitação de recurso HHH-9808 pelo mantenedor do núcleo Steve Ebersole em 2016:
Para uma explicação detalhada, veja: Por que não podemos aplicar @ColumnTransformer ao campo @Id (chave primária)? .
Relacionado
Essa restrição também seria o problema neste caso: @ColumnTransformer não é usado em select . A solução foi usar uma coluna diferente como primary-key com
@Id
.Soluções alternativas
Para fazer a transformação do endereço IP funcionar, eu poderia pensar nestas soluções alternativas:
UPDATE TABLE gage_requests.printers SET ip = INET_NTOA(ip)
. Então você não precisa de transformação em Java, mas de uma validação noaddress
campo, para garantir o formato correto.INET_NTOA
paraINET_ATON
os getters/setters Java para o campoaddress
.@Id
paranickname
Do seu problema, acredito que tenho duas causas principais que podem fazer com que o endereço IP não seja convertido corretamente, permanecendo um número inteiro:
Da minha experiência com o Hibernate, algumas versões podem não suportar totalmente a
@ColumnTransformer
anotação para certas consultas. Eu pesquisei um pouco sobre o tópico, e parece que o Hibernate 5.4+ suporta totalmente essa anotação, de acordo com esta documentação: https://docs.jboss.org/hibernate/orm/5.4/javadocs/org/hibernate/annotations/ColumnTransformer . Aqui, ele descreve o uso da@ColumnTransformer
anotação no Hibernate 5.4, resultando que ele a suporta.Consultas nativas tendem a funcionar melhor com esse tipo de anotação. Eu sugiro também tentar criar sua consulta algo como: