postgresqlquarkusmybatis

Why MyBatis can't map the JSONB type to a Map<String, Object> or to JsonNode?


I have a DTO as:

@Data
@Accessors(chain = true)
public class UserHasAssetDTO {

    private Integer id;

    ...

    private Map<String, Object> props;
}

and a Repository where I have the method:

@Select("select id, ..., props from bla bla bla")
List<UserHasAssetDTO> getALLAssetsFilteredByDate(@Param("username") String username, @Param("startDate") String startDate, @Param("endDate") String endDate);

Note: the field props in my PostgreSQL DB is JSONB type.

If I execute the query manually, I can see that the props are populated correctly.

But, when in my service:

    public List<UserHasAssetDTO> userHasALLAssets(String user, String start, String end) {

        List<UserHasAssetDTO> userHasAssetDTOList = userHasAssetRepository.getALLAssetsFilteredByDate(user, start, end);

        log.info("userHasALLAssets: {}", userHasAssetDTOList);

        return userHasAssetDTOList;
    }

The props fields ar null!!!

I suspect that I am not mapping PostgreSQL's JSONB type correctly on my DTO.

How can I fix it so that the props fields are populated correctly?


Solution

  • Solved with this Class:

    @MappedJdbcTypes({JdbcType.JAVA_OBJECT})
    @MappedTypes({JsonNode.class})
    public class JsonNodeTypeHandler extends BaseTypeHandler<JsonNode> {
    
        private static final ObjectMapper objectMapper = new ObjectMapper();
    
        @Override
        public void setNonNullParameter(PreparedStatement ps, int i, JsonNode parameter, JdbcType jdbcType)
                throws SQLException {
            PGobject jsonObject = new PGobject();
            jsonObject.setType("jsonb");
            try {
                jsonObject.setValue(parameter.toString());
                ps.setObject(i, jsonObject);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    
        @Override
        public JsonNode getNullableResult(ResultSet rs, String columnName) throws SQLException {
            String jsonSource = rs.getString(columnName);
            if (jsonSource != null) {
                try {
                    return objectMapper.readTree(jsonSource);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
            return null;
        }
    
        @Override
        public JsonNode getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
            String jsonSource = rs.getString(columnIndex);
            if (jsonSource != null) {
                try {
                    return objectMapper.readTree(jsonSource);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
            return null;
        }
    
        @Override
        public JsonNode getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
            String jsonSource = cs.getString(columnIndex);
            if (jsonSource != null) {
                try {
                    return objectMapper.readTree(jsonSource);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
            return null;
        }
    }
    

    and JsonNode type in my DTO.