3

I am trying to insert json into json column using spring webflux with postgres sql. I have created custom converter for reading and writing. The issue is existing json values becomes null, whenever trying to update the record. The new value is inserted as json along with null object as well. Please let me know where i am doing it wrong

@Configuration
@AllArgsConstructor
@EnableR2dbcRepositories("com.gohunt.hd.hunts.entity")
public class ReactivePostgresConfig extends AbstractR2dbcConfiguration {
private final ObjectMapper objectMapper;

@Bean
@Override
public R2dbcCustomConversions r2dbcCustomConversions() {
    System.out.println("r2dbcCustomConversions ++++++++++++++++++");
    List<Converter<?, ?>> converters = new ArrayList<>();
    converters.add(new JsonToMapConverter(objectMapper));
    converters.add(new MapToJsonConverter(objectMapper));
    return new R2dbcCustomConversions(getStoreConversions(), converters);
}

@Override
public ConnectionFactory connectionFactory() {
    // TODO Auto-generated method stub
    return null; // configured via properties file
}


@Slf4j
@ReadingConverter
@AllArgsConstructor
public class JsonToMapConverter implements Converter<Json, List<SeasonsJsonDto>> {

private final ObjectMapper objectMapper;
@Override
public List<SeasonsJsonDto> convert(Json json) {
    try {
        System.out.println("json +++++++++++++ "+json);
        //return AppJsonUtil.parseMessageAsList(json.toString(), SeasonsJsonDto.class);
        return Arrays.asList(objectMapper.readValue(json.toString(), SeasonsJsonDto[].class));
        
    } catch (Exception e) {
        log.error("Problem while parsing JSON: {}", json, e);
    }
    return new ArrayList<SeasonsJsonDto>();
}

}

@Slf4j
@WritingConverter
@AllArgsConstructor
public class MapToJsonConverter implements Converter<List<SeasonsJsonDto>, Json> {
private final ObjectMapper objectMapper;

@Override
public Json convert(List<SeasonsJsonDto> source) {
    try {
       return Json.of(objectMapper.writeValueAsString(source));
    } catch (JsonProcessingException e) {
        log.error("Error occurred while serializing map to JSON: {}", source, e);
    }
    return Json.of("");
}

}

@Table("aaaa")
@Data
public class HuntsDetail extends BaseEntity implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @Column("id")
    private Long id;

    @Column("hunter_id")
    private Long hunterId;

    @Column("hunts_collection_id")
    private String huntCollectionId;

    @Column("folder_id")
    private Long folderId;

    @Column("hunts_coverimgUrl")
    private String huntsCoverImgUrl;

    @Column("seasons_dtl")
    private List<SeasonsJsonDto> seasonsDtl; // json datatype in DB  using above converters to get it as List or json while reading/writing.

}
user1111880
  • 443
  • 5
  • 8
  • 26
  • We tried with sysout as well in each converter as well, but those are not getting printed . so i think they are not getting called. please clarify – user1111880 Jan 04 '22 at 20:51
  • `The issue is existing json values becomes null, whenever trying to update the record`i have no idea what you mean by this. Also `The new value is inserted as json along with null object as well.` i have no idea what you mean by this either. – Toerktumlare Jan 05 '22 at 12:32
  • could you please share your complete code if possible?. Also have you looked at this sample -> https://github.com/hantsy/spring-r2dbc-sample/blob/master/data-r2dbc-repositories/src/main/java/com/example/demo/Post.java – Harry Jan 05 '22 at 21:55
  • @Toerktumlare - I am trying to use custom converter to convert from Json to list or vice -versa. I have defined customer converter for that and in entity defined json column as List (check enity class). The issue while reading the data List object is always contain null even if DB column contains data. So, when trying to update this, only new data gets inserted to DB and not appends it . – user1111880 Jan 07 '22 at 18:12
  • @Harry - I am trying to use custom converter to convert from Json to list or vice -versa. I have defined customer converter for that and in entity defined json column as List (check enity class). The issue while reading the data List object is always contain null even if DB column contains data. So, when trying to update this, only new data gets inserted to DB and not appends it . – user1111880 Jan 07 '22 at 18:12
  • @user1111880 You can create a wrapper class which has a property: private List seasonsDtl; Then create a custom converter from/to MyWrapperClass/Json. That should work but your JSON will have to have a property named seasonsDtl which will hold a list of SeasonsJsonDto – NikolaB Jan 10 '22 at 08:37

2 Answers2

0

I think the answer here might be a hint.

https://github.com/spring-projects/spring-data-r2dbc/issues/298#issuecomment-586965017

How about wrapping a List<?> in a outer class? I think it's because of Java's Generic Type Erasure, so that can not find the exact converter.

mys
  • 119
  • 1
  • 12
0

I know this answer is late, but I feel like I should add another perspective on how to do this. I've done this in another way by using a json field and then converting to whatever object I needed in a mapping step.

For example, I might have an entity like this:

import io.r2dbc.postgresql.codec.Json;

@Table("table_name")
@Data
@Builder
public class MyObject {
    @Id
    private Integer id;
    private Json data;
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;
}

With a DTO class like

@Data
@Builder
public class MyObjectDTO {
    private Integer id;
    private List<YourObjectType> data;
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;
}

And then a mapping class that does something like this:

public MyObjectDTO to(MyObject myObj) {
    try {
        ObjectMapper objectMapper = 
        List<YourObjectType> yourList = objectMapper.readValue(
            myObj.getData().asString(), 
            new TypeReference<List<YourObjectType>>() {});

        return MyObjectDTO.builder()
                .id(myObj.getId())
                .data(yourList)
                .createdAt(myObj.getCreatedAt())
                .updatedAt(myObj.getUpdatedAt())
                .build();
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}
BeLEEver
  • 251
  • 4
  • 11