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

  1. create table field with jsonb type
  2. Query DB with pgjdbc 42.2.20 and mybatis 3.5.6 to get the java type of the field is String
  3. Query DB with pgjdbc 42.2.8 and mybatis 3.5.6 to get the java type of the field is PGObject

Expected behaviour Expect jsonb type to be converted to PGObject to guarantee compatibility,actually It is converted to String type,

analyze

  1. Java persistence framework use PgResultSetMetaData getColumnClassName(jdk standard method) method to get jsonb type column class name
  2. In version 42.2.20, the java type of jsonb field is set to java.lang.String and in version before 42.2.13 it is set to java.lang.Object
  3. 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)

Most upvoted comments

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

This seems to be the intended change. ( #1879 )

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.