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?
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.