implement ResultSetMetadata#getColumnType() to unblock native query non-entity DTO usage

XMLWordPrintableJSON

    • Type: Task
    • Resolution: Unresolved
    • Priority: Major - P3
    • None
    • 4
    • None
    • None
    • None
    • None
    • None
    • None
    • None

      When native query is used to go about selection query (JDBC's ResultSet will get involved), it is good practice to specify DTO `ResultClass` class as example below:

      static class BookCountByAuthor {
          String _id;
          int count;
      
          public BookCountByAuthor(String _id, int count) {
              this._id = _id;
              this.count = count;
          }
      }
      
      var nativeQuery =
              """
              {
                  aggregate: "books",
                  pipeline: [
                      { $match :  { author: { $eq: :author } } },
                      { $group: { _id: "$author", count: {$count: {} }} },
                      { $project: { _id: 1, count: 1 } }
                  ]
              }
              """; 
      var query = session.createNativeQuery(nativeQuery, BookCountByAuthor.class);
      var bookCountByAuthor = query.getSingleResult();

      Currently the above query won't work for Hibernate requires guidance on how to interpret the returned ResultSet after server running native query; it knows of projection list size and names, but internally Hibernate would feel lost on invoking which ResultSet's getter method to fetch field value (`getString(idx)`, `getDouble(idx)`, etc.). That is why we need to provide ResultSetMetadata info, particularly implementing the following method:

      public int getColumnType(int column) throws SQLException; 

      Note that if Entity class is provided as ResultClass, no metadata info is needed for Hibernate knows of all the mapping details from entity class (each field's JDBC type including how to bind and extract) and SQL AST processing. So this ticket's scope is rather limited.

      One of the possible implementation is to implement the getColumnType() to return invariably `java.sql.Types.JAVA_OBJECT` as below:

      @Override
      public int getColumnType(int column) throws SQLException {
          return Types.JAVA_OBJECT;
      } 

      which will end up with Hibernate invoking the following new ResultSet API method (never used in Hibernate so it won't interfere with existing workflow):

      @Override
      public @Nullable Object getObject(int columnIndex) throws SQLException {
          // invoke existing ValueConversions to transform BsonValue to Java value; might enrich by dealing with Bson array or document (recursively!)
      }
      

            Assignee:
            Unassigned
            Reporter:
            Nathan Xu
            None
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: