Olá a todos. O Hibernate Reactive oferece suporte a UserTypes personalizados? Eu quero usar o tipo JSONB Postgres e para isso eu estava usando a seguinte biblioteca https://github.com/vladmihalcea/hibernate-types que cria seus tipos personalizados com base no AbstractSingleColumnStandardBasicType do Hibernate. Infelizmente, apenas mudando do Hibernate para o Hibernate Reactive, as colunas que usam esses tipos são sempre nulas nas entidades. Como alternativa, encontrei este artigo que constrói seu suporte a JSONB Postgres no UserType do Hibernate. Existe alguma limitação conhecida em torno da definição de tipos personalizados e do uso do Hibernate Reactive no momento?
Olá, não testei UserType
porque essa interface está bastante ligada ao JDBC. (Embora, em princípio, talvez pudesse funcionar principalmente.)
Em vez disso, minha ideia era que as pessoas pudessem usar conversores JPA. Eu testei isso e AFAIK funciona. Você já tentou isso?
Eu tentei com um teste rápido usando UserType e não parece funcionar porque o PgClient lança uma exceção ao executar a consulta.
Eu tentei com um teste rápido usando UserType e não parece funcionar porque o PgClient lança uma exceção ao executar a consulta.
Mas isso pode ser apenas porque nossa camada JDBC falsa está incompleta. (Alguns métodos não implementados.)
Para esclarecer, tentei o exemplo usando a biblioteca vlad:
@TypeDefs({
@TypeDef(name = "json", typeClass = JsonStringType.class),
@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
})
@Entity(name="GuineaPig")
@Table(name="Pig")
public static class GuineaPig {
<strong i="6">@Id</strong>
private Integer id;
private String name;
@Type(type = "jsonb")
@Column(columnDefinition = "jsonb")
private Location location;
Este é o erro:
Caused by: io.vertx.core.impl.NoStackTraceThrowable: Parameter at position[0] with class = [com.fasterxml.jackson.databind.node.ObjectNode] and value = [{"country":"UK","city":"Gotham"}] can not be coerced to the expected class = [java.lang.Object] for encoding.
Parece que o cliente pg reativo usa um tipo diferente para converter para JSON.
@gavinking Devemos oferecer suporte a algum tipo de mapeamento para os tipos pg-client ?
JSON (io.reactiverse.pgclient.data.Json)
JSONB (io.reactiverse.pgclient.data.Json)
POINT (io.reactiverse.pgclient.data.Point)
LINE (io.reactiverse.pgclient.data.Line)
LSEG (io.reactiverse.pgclient.data.LineSegment)
BOX (io.reactiverse.pgclient.data.Box)
PATH (io.reactiverse.pgclient.data.Path)
POLYGON (io.reactiverse.pgclient.data.Polygon)
CIRCLE (io.reactiverse.pgclient.data.Circle)
Acho que o cliente está esperando um objeto do tipo io.reactiverse.pgclient.data.Json
. Parece que lidamos com UserType
corretamente, no entanto
Certo, é isso que eu quis dizer no meu comentário acima. Nossos adaptadores JDBC não estão nem perto de uma implementação completa do JDBC, e eu vejo como bem provável que nunca estarão. Em particular, para tipos JDBC mais “exóticos”, pode ser bastante difícil mapeá-los de / para a API Vert.x.
Devemos oferecer suporte a algum tipo de mapeamento para os tipos pg-client?
Bem, claro, se for razoavelmente fácil de fazer.
Mas se não, devemos considerar que talvez UserType
simplesmente não seja a abstração certa aqui e procurar uma abordagem diferente.
Quero dizer, na medida em que UserType
s existentes podem funcionar sem fazer nada horrível, então com certeza, vamos fazê-los funcionar. Isso tornará a migração mais fácil. Mas eu acho que é possível que rapidamente encontremos limitações quanto ao que é realmente possível lá.
vou dar uma olhada
vou dar uma olhada
Como primeiro passo, devemos adicionar um teste para um totalmente simples UserType
que não usa nenhum tipo de banco de dados extravagante, apenas para verificar se o conceito básico funciona (não vejo por que não deveria )
@gavinking Não, eu não testei os conversores ainda porque estou usando o Hibernate junto com a biblioteca de tipos do Hibernate. Mas a sugestão de usar conversores significaria que no final irei colocar um Postgres Text / Varchar simples no banco de dados e não um tipo Postgres JSONB.
@gavinking Não, eu não testei os conversores ainda porque estou usando o Hibernate junto com a biblioteca de tipos do Hibernate. Mas a sugestão de usar conversores significaria que no final irei colocar um Postgres Text / Varchar simples no banco de dados e não um tipo Postgres JSONB.
Para esclarecer: você está preocupado com o tipo que você tem no Java ou no banco de dados? Existem duas coisas diferentes aqui.
JSONB
como o tipo de coluna, mas, em princípio, eu pensaria que os drivers podem converter strings para esse tipo de forma transparente. (Não tenho certeza, nunca tentei.)io.reactiverse.pgclient.data.Json
como o tipo Java em seu modelo. Esse é um problema totalmente diferente e, de fato, exigiria algo mais como UserType
.@gavinking
Quero usar o tipo Postgres JSONB
. Acho que não é suportado diretamente pelo Hibernate. É por isso que confiei neste https://vladmihalcea.com/how-to-map-json-objects-using-generic-hibernate-types/ . Ou, por exemplo, este https://thorben-janssen.com/persist-postgresqls-jsonb-data-type-hibernate/ onde o guia usa UserType.
Certo, eu entendo isso, mas você já tentou fazer algo realmente simples, como mapear um Java String
para uma coluna do tipo JSONB
? Isso seria bom o suficiente se funcionasse?
@gavinking Não, eu não tentei ainda. Sim, seria bom o suficiente. Eu só precisaria converter os objetos JSON em string JSON antes de tentar inserir minhas entidades no banco de dados.
OK, então pode ser que o cliente Vert.x já suporte essa conversão de tipo, precisaríamos tentar, mas mesmo que não, acho que provavelmente deveria.
@DavideD qual é o status aqui? Você quer que eu dê uma olhada mais de perto neste?
Eu fui desviado. Sinta-se à vontade para resolver isso se tiver tempo.
Em # 301, adicionei um teste demonstrando que UserType
s trabalham em RH, pelo menos até o ponto em que nossos adaptadores PreparedStatement
e ResultSet
são implementações fiéis de JDBC ( o que não é particularmente grande).
@gavinking Devemos oferecer suporte a algum tipo de mapeamento para os tipos pg-client ?
JSON (io.reactiverse.pgclient.data.Json) JSONB (io.reactiverse.pgclient.data.Json) POINT (io.reactiverse.pgclient.data.Point) LINE (io.reactiverse.pgclient.data.Line) LSEG (io.reactiverse.pgclient.data.LineSegment) BOX (io.reactiverse.pgclient.data.Box) PATH (io.reactiverse.pgclient.data.Path) POLYGON (io.reactiverse.pgclient.data.Polygon) CIRCLE (io.reactiverse.pgclient.data.Circle)
Portanto, a questão agora é: podemos fazer com que getObject()
e setObject()
em nossos adaptadores JDBC suportem esses tipos sem criar uma dependência rígida para o cliente PostgreSQL?
Seria possível ter algo como:
@Type(type="passthrough")
Circle circle
Isso não faz nenhuma conversão, mas apenas passa o valor como está?
Portanto, a questão agora é: podemos fazer com que
getObject()
esetObject()
em nossos adaptadores JDBC suportem esses tipos sem criar uma dependência rígida para o cliente PostgreSQL?
Bem, eu tentei isso e aparentemente não precisamos fazer nada de especial para lidar com io.vertx.core.json.JsonObject
no Postgres ou MySQL. Você pode simplesmente usar getObject()
/ setObject()
do seu UserType
.
Isso funciona:
public class Json implements UserType {
<strong i="15">@Override</strong>
public int[] sqlTypes() {
return new int[] {Types.OTHER};
}
<strong i="16">@Override</strong>
public Class returnedClass() {
return JsonObject.class;
}
<strong i="17">@Override</strong>
public boolean equals(Object x, Object y) throws HibernateException {
return Objects.equals(x,y);
}
<strong i="18">@Override</strong>
public int hashCode(Object x) throws HibernateException {
return Objects.hashCode(x);
}
<strong i="19">@Override</strong>
public Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner) throws HibernateException, SQLException {
return rs.getObject(names[0]);
}
<strong i="20">@Override</strong>
public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session) throws HibernateException, SQLException {
if (value==null) {
st.setNull(index, Types.OTHER);
}
else {
st.setObject(index, value);
}
}
...
}
Seria possível ter algo como:
@Type(type="passthrough") Circle circle
Isso não faz nenhuma conversão, mas apenas passa o valor como está?
Sim, isso também funcionaria.
Consulte 54434c94b3ff57261fd905abaeb25961b2ed285c.
Eu diria que podemos encerrar esse problema.
E quanto aos outros tipos, como io.reactiverse.pgclient.data.Circle
por exemplo?
@akoufa agora para dar respostas concretas às suas perguntas originais:
O Hibernate Reactive suporta
UserTypes
customizado?
A resposta é sim!
No entanto, você precisa estar ciente de que, embora exponhamos algo que se parece muito com JDBC para seu UserType
, nos bastidores não há conexão JDBC, mas um cliente de banco de dados totalmente diferente, sem bloqueio. Portanto, algumas coisas simplesmente não vão funcionar.
Eu estava usando a seguinte biblioteca https://github.com/vladmihalcea/hibernate-types
Então, acho que você precisa ser bem realista sobre isso. A biblioteca acima foi escrita para funcionar com JDBC, então enquanto algumas de suas UserType
s podem funcionar, outras não.
Como alternativa, encontrei este artigo que constrói seu suporte JSONB Postgres no Hibernate
UserType
.
Dê uma olhada em como implementei isso no conjunto de testes. A ideia básica é que você precisa passar um Vert.x JsonObject
para o cliente Vert.x PostgreSQL ou MySQL apenas chamando setObject()
.
E quanto aos outros tipos, como
io.reactiverse.pgclient.data.Circle
por exemplo?
Deve ser o mesmo negócio, embora eu não teste.
A propósito, io.reactiverse.pgclient.data
está morto. É para uma versão anterior do cliente. Não é para isso que você deveria estar olhando.
Aqui está a lista atual de tipos:
https://vertx.io/docs/vertx-pg-client/java/#_postgresql_type_mapping
Eu entendo isso, mas você já tentou fazer algo realmente simples, como apenas mapear uma string Java para uma coluna do tipo JSONB?
...
OK, então pode ser que o cliente Vert.x já suporte essa conversão de tipo, precisaríamos tentar, mas mesmo que não, acho que provavelmente deveria.
De acordo com os documentos que eu ligadas acima, isso não funciona. Eu até testei escrever um inteiro diretamente em uma coluna JSONB
-types e funcionou.
Portanto, em princípio, você nem precisa mexer em JsonObject
se não quiser. (Provavelmente, é mais limpo.)
Claro, você poderia adicionar um teste para alguns dos outros tipos específicos? Como linha ou círculo. Para que possamos mostrar a aparência do mapeamento
Oi!
Vocês viram alguma biblioteca como https://github.com/vladmihalcea/hibernate-types para usar com hibernate-reativo?
Se isso ainda não existir, gostaria de construir algo para o meu projeto (usando quarkus). Eu uso muitas colunas JSON no postgres.
Mas eu não sei se entendi errado, mas hibernate-reactive
só permite o tipo personalizado implementando a partir da interface UserType
? (http://hibernate.org/reactive/documentation/1.0/reference/html_single/#_custom_types)
@AlexandreGuidin , acho que @gavinking já respondeu suas perguntas em um dos comentários anteriores: https://github.com/hibernate/hibernate-reactive/issues/279#issuecomment -666289449
Mas se eu estiver faltando alguma coisa, fique à vontade para fazer mais algumas perguntas.