String 与JSONB相关的PostgreSQL Hibernate类型数据转换错误
由于hibernate本机不支持JSONB,所以我实现了自定义类型。我可以毫无问题地从表ad_my_表中读取数据。然而,在编写时,我得到了数据转换错误。我还尝试使用第三方解决方案,如“hibernate类型”库,但也遇到了同样的错误 MyTable实体类:String 与JSONB相关的PostgreSQL Hibernate类型数据转换错误,string,postgresql,spring-boot,hibernate,jsonb,String,Postgresql,Spring Boot,Hibernate,Jsonb,由于hibernate本机不支持JSONB,所以我实现了自定义类型。我可以毫无问题地从表ad_my_表中读取数据。然而,在编写时,我得到了数据转换错误。我还尝试使用第三方解决方案,如“hibernate类型”库,但也遇到了同样的错误 MyTable实体类: import com.sample.console.backend.dao.entity.JsonbUserType; import org.hibernate.annotations.ColumnDefault; import org.h
import com.sample.console.backend.dao.entity.JsonbUserType;
import org.hibernate.annotations.ColumnDefault;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.TypeDef;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.GenerationType;
import javax.persistence.SequenceGenerator;
import javax.persistence.Column;
import javax.persistence.Enumerated;
@Entity
@Table(name = "ad_my_table")
@TypeDef(name = "jsonb", typeClass = JsonbUserType.class)
public class CustomClientEntity
{
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "my_table_id_seq")
@SequenceGenerator(name = "my_table_id_seq", sequenceName = "ad_my_table_id_seq", allocationSize = 1)
private Long id;
@Column(name = "filename")
private String fileName;
@Column(name = "config", columnDefinition = "jsonb")
@Type(type = "jsonb")
private String config;
public Long getId()
{
return id;
}
public void setId(Long id)
{
this.id = id;
}
public String getFileName()
{
return fileName;
}
public void setFileName(String fileName)
{
this.fileName = fileName;
}
public String getConfig()
{
return config;
}
public void setConfig(String config)
{
this.config = config;
}
}
JsonbUserType.class实现UserType:
import org.apache.commons.lang3.StringUtils;
import org.hibernate.usertype.UserType;
import org.postgresql.util.PGobject;
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
public class JsonbUserType implements UserType {
public static final String JSONB_TYPE = "jsonb";
@Override
public Class<String> returnedClass() {
return String.class;
}
@Override
public int[] sqlTypes() {
return new int[]{ Types.JAVA_OBJECT };
}
@Override
public Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner) throws HibernateException, SQLException {
if (names.length <= 0) { return null; }
final String dbData = rs.getString(names[0]);
String result = null;
if (StringUtils.isNotBlank(dbData)) {
String json = dbData.startsWith("\"") ? dbData.substring(1, dbData.length() - 1) : dbData;
result = StringEscapeUtils.unescapeJson(json);
}
return result;
}
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session)
throws HibernateException, SQLException {
if (value instanceof String && StringUtils.isNotBlank((String)value))
{
PGobject pgObject = new PGobject();
pgObject.setType(JSONB_TYPE);
pgObject.setValue((String)value);
st.setObject(index, pgObject, Types.OTHER);
}
else {
st.setNull(index, Types.OTHER);
}
}
@Override
public Object deepCopy(Object value) throws HibernateException {
return value;
}
@Override
public boolean isMutable() {
return true;
}
@Override
public boolean equals(Object x, Object y) throws HibernateException {
if(x == null) { return y == null; }
return x.equals(y);
}
@Override
public int hashCode(Object x) throws HibernateException {
assert (x != null);
return x.hashCode();
}
@Override
public Object assemble(Serializable cached, Object owner) throws HibernateException {
return this.deepCopy( cached);
}
@Override
public Serializable disassemble(Object value) throws HibernateException {
return (String)this.deepCopy( value);
}
@Override
public Object replace(Object original, Object target, Object owner) throws HibernateException {
return original;
}
}
import com.sample.console.backend.dao.entity.JsonbUserType;
import org.hibernate.dialect.PostgreSQL10Dialect;
import java.sql.Types;
public class CustomPostgreSQLDialect extends PostgreSQL10Dialect
{
public CustomPostgreSQLDialect() {
super();
registerColumnType(Types.JAVA_OBJECT, JsonbUserType.JSONB_TYPE);
}
}
Caused by: org.h2.jdbc.JdbcSQLDataException: Data conversion error converting "X'aced000...74227d' (AD_MY_TABLE: ""CONFIG"" ""JSONB"")"; SQL statement: insert into ad_my_table (config, filename, id) values (?, ?, ?) [22018-200]
Caused by: org.h2.message.DbException: Data conversion error converting "OTHER to JSON" [22018-200]
我收到的错误:
import org.apache.commons.lang3.StringUtils;
import org.hibernate.usertype.UserType;
import org.postgresql.util.PGobject;
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
public class JsonbUserType implements UserType {
public static final String JSONB_TYPE = "jsonb";
@Override
public Class<String> returnedClass() {
return String.class;
}
@Override
public int[] sqlTypes() {
return new int[]{ Types.JAVA_OBJECT };
}
@Override
public Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner) throws HibernateException, SQLException {
if (names.length <= 0) { return null; }
final String dbData = rs.getString(names[0]);
String result = null;
if (StringUtils.isNotBlank(dbData)) {
String json = dbData.startsWith("\"") ? dbData.substring(1, dbData.length() - 1) : dbData;
result = StringEscapeUtils.unescapeJson(json);
}
return result;
}
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session)
throws HibernateException, SQLException {
if (value instanceof String && StringUtils.isNotBlank((String)value))
{
PGobject pgObject = new PGobject();
pgObject.setType(JSONB_TYPE);
pgObject.setValue((String)value);
st.setObject(index, pgObject, Types.OTHER);
}
else {
st.setNull(index, Types.OTHER);
}
}
@Override
public Object deepCopy(Object value) throws HibernateException {
return value;
}
@Override
public boolean isMutable() {
return true;
}
@Override
public boolean equals(Object x, Object y) throws HibernateException {
if(x == null) { return y == null; }
return x.equals(y);
}
@Override
public int hashCode(Object x) throws HibernateException {
assert (x != null);
return x.hashCode();
}
@Override
public Object assemble(Serializable cached, Object owner) throws HibernateException {
return this.deepCopy( cached);
}
@Override
public Serializable disassemble(Object value) throws HibernateException {
return (String)this.deepCopy( value);
}
@Override
public Object replace(Object original, Object target, Object owner) throws HibernateException {
return original;
}
}
import com.sample.console.backend.dao.entity.JsonbUserType;
import org.hibernate.dialect.PostgreSQL10Dialect;
import java.sql.Types;
public class CustomPostgreSQLDialect extends PostgreSQL10Dialect
{
public CustomPostgreSQLDialect() {
super();
registerColumnType(Types.JAVA_OBJECT, JsonbUserType.JSONB_TYPE);
}
}
Caused by: org.h2.jdbc.JdbcSQLDataException: Data conversion error converting "X'aced000...74227d' (AD_MY_TABLE: ""CONFIG"" ""JSONB"")"; SQL statement: insert into ad_my_table (config, filename, id) values (?, ?, ?) [22018-200]
Caused by: org.h2.message.DbException: Data conversion error converting "OTHER to JSON" [22018-200]
使用将Jsonb类型创建为clob的连接字符串,
jdbc:h2:mem:;INIT=创建域(如果不存在jsonb作为CLOB)代码>。只要将字段定义为实体中的字符串,就可以很好地执行此操作。如果将实体中的字段定义为CustomJson对象,则它只支持DB读取操作
这项工作:
@Column(name = "config", columnDefinition = "jsonb")
@Type(type = "jsonb")
private String config;
这不支持读取操作
@Column(name = "config", columnDefinition = "jsonb")
@Type(type = "jsonb")
private MyJsonObject config;
你查清楚了吗?我也有同样的问题。它在实际对抗Postgres时有效,但在对抗H2时无效。我没有使用自定义方言来注册JSONB支持,而是使用了一个连接字符串,将JSONB类型创建为JSON(以解决H2 JSON==Postgres JSONB问题),但我仍然有相同的问题:jdbc:H2:mem:;INIT=如果不存在JSONB作为JSON创建域