pgjdbc: Upgrading jdbc causes the Java type of jsonb to change from PGObject to String
Describe the issue
There are many fields of jsonb type in our database. These fields were converted to PGObject type before v42.2.13. When I upgraded jdbc to 42.2.20, these fields were converted to String type. Caused a lot of errors.
Driver Version? 42.2.20
Java Version? 1.8.0_191 OS Version? macOS
PostgreSQL Version? 10.4 and 12.4 all tested
To Reproduce
- create table field with jsonb type
- Query DB with pgjdbc
42.2.20and mybatis 3.5.6 to get the java type of the field isString - Query DB with pgjdbc
42.2.8and mybatis 3.5.6 to get the java type of the field isPGObject
Expected behaviour Expect jsonb type to be converted to PGObject to guarantee compatibility,actually It is converted to String type,
analyze
- Java persistence framework use PgResultSetMetaData
getColumnClassName(jdk standard method) method to getjsonbtype column class name - In version 42.2.20, the java type of jsonb
fieldis set tojava.lang.Stringand in version before 42.2.13 it is set tojava.lang.Object - And then java persistence framework read query result
- In version 42.2.20, Get the result through the getString method of PgResultSet, because ColumnClassName is string.
- In version 42.2.8, Get the result through the getObject method of PgResultSet, then the method getObject of PgConnection create PgObject type result ,because the db field type is jsonb and ColumnClassName is Object.
caused by this commit and when oid is 3802(jsonb): https://github.com/pgjdbc/pgjdbc/blob/529e5dc3a8f071ad4946daf3bde1422c21a99524/pgjdbc/src/main/java/org/postgresql/jdbc/TypeInfoCache.java#L652 reproducer code And Logs
- code
public class Test {
public static void main(String[] args) {
String url = "jdbc:postgresql://localhost:5432/pms";
Properties props = new Properties();
props.setProperty("user", "test");
props.setProperty("password", "test");
try (Connection conn = DriverManager.getConnection(url, props)) {
try (Statement statement = conn.createStatement()) {
try (ResultSet rs = statement.executeQuery("select * from xxx")) {
if (rs.next()) {
PgResultSetMetaData metaData = (PgResultSetMetaData) rs.getMetaData();
System.out.println("jsonb column type name:" + metaData.getColumnTypeName(index of jsonb column));
System.out.println("jsonb column class name:" + metaData.getColumnClassName(index of jsonb column));
//42.2.20 Use getString through the column type to return String object
System.out.println("Get jsonb value: " + rs.getString(index of jsonb column));
//42.2.8 use getObject through the column type to return PGObject
System.out.println("Get jsonb Type: " + rs.getObject(index of jsonb column).getClass().getName());
}
}
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
- output with 42.2.20
json column type name:jsonb
json column class name:java.lang.String
Get jsonb value: jsonb field result
with 42.2.8
jsonb column type name:jsonb
jsonb column class name:java.lang.Object
Get jsonb Object: org.postgresql.util.PGobject
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Reactions: 1
- Comments: 16 (9 by maintainers)
money is not something I am going to fix. Nobody should ever use it.
Yes, this should not have been changed in 42.2.x
maybe, but this change affects all jsonb type data. When querying data from the database, the original jsonb type column is pgobject and then becomes a string, causing many business exceptions.