以下代码在 postgresql 上的 Hibernate 6.1 和 6.4 之间的行为不同:
var rows =
session
.createNativeQuery("SELECT CAST('[1,2,3]' as jsonb) as data, 2 as id", Object[].class)
.addScalar("data")
.addScalar("id", StandardBasicTypes.INTEGER)
.list();
rows.forEach(row -> System.out.println(row[0].getClass() + " -> " + row[0]));
6.1 的输出:
class java.util.ArrayList -> [1, 2, 3]
6.4 的输出:
class java.lang.String -> [1, 2, 3]
在6.1中,它将jsonb列转换为ArrayList;但在 6.4 上它只是将其读取为字符串。我尝试传递一堆不同的
StandardBasicTypes
,但没有一个能让 6.4 表现得像 6.1。 那么,我该如何在 6.4 中做到这一点?
这里是重现此问题的代码: https://github.com/chadselph/hibernate-json-native-query
使用用户类型!
var rows =
session
.createNativeQuery("SELECT CAST('[1,2,3]' as jsonb) as data, 2 as id", Object[].class)
.addScalar("data", JsonbType.class)
.addScalar("id", StandardBasicTypes.INTEGER)
.list();
rows.forEach(row -> System.out.println(row[0].getClass() + " -> " + row[0]));
public class JsonbType implements UserType {
private final ObjectMapper objectMapper = new ObjectMapper();
@Override
public int getSqlType() {
// Postgres specific type for jsonb
return Types.OTHER;
}
@Override
public Class returnedClass() {
return ArrayList.class;
}
@Override
public boolean equals(Object x, Object y) throws HibernateException {
return Objects.equals(x, y);
}
@Override
public int hashCode(Object x) throws HibernateException {
assert (x != null);
return x.hashCode();
}
@Override
public Object nullSafeGet(ResultSet rs, int position, SharedSessionContractImplementor session, Object owner) throws SQLException{
try {
final String json = rs.getString(position);
return json == null ? null : objectMapper.readValue(json, ArrayList.class);
} catch (IOException e) {
throw new HibernateException("Error converting jsonb to ArrayList", e);
}
}
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session)
throws HibernateException, SQLException {
try {
if (value == null) {
st.setNull(index, Types.OTHER);
} else {
st.setObject(index, objectMapper.writeValueAsString(value), Types.OTHER);
}
} catch (JsonProcessingException e) {
throw new HibernateException("Error converting ArrayList to jsonb", e);
}
}
@Override
public Object deepCopy(Object value) {
try {
final String json = objectMapper.writeValueAsString(value);
return objectMapper.readValue(json, ArrayList.class);
} catch (IOException e) {
throw new HibernateException("Error deep copying jsonb", e);
}
}
@Override
public boolean isMutable() {
return true;
}
@Override
public Serializable disassemble(Object value) {
return (Serializable) this.deepCopy(value);
}
@Override
public Object assemble(Serializable cached, Object owner) {
return this.deepCopy(cached);
}
@Override
public Object replace(Object detached, Object managed, Object owner) {
return this.deepCopy(detached);
}
}
我将 Object 更改为 JsonNode 并且它有效))