0

I have implemented method AttributeConverter.convertToEntityAttribute to load json data from the db. I am not trying to persist data, but for some reason convertToDatabaseColumn is being called.

This is what happens:
1. I call a repository method
2. then a call to AttributeConverter.convertToEntityAttribute follows -> returns a list of entity Cx. Till this point everything is normal.
3. But for some reason AttributeConverter.convertToDatabaseColumn is called right after, with that same list of entity Cx as argument -> returns stringV
4.Now convertToEntityAttribute is called again with stringV as argument, which is also strange.

Could it be that a @OneToOne relation is causing this? Why is this executing convertToDatabaseColumn if I'm not persisting an entity, at least explicitly?

All of this happens just by calling a single method in one of my repository classes:

Here is the code

public interface RSTRepository extends CrudRepository<RST, Long> {

    List<RST> findByDuctNameIgnoreCase(String ductName);
}

@Entity
@Table(name="r_s_t")
public class RST {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;

    @OneToOne
    @JoinColumn(name = "r_s_id")
    private Rs rs;

    @Column(name = "channel")
    private String channelName;
    ...
}

@Entity
@Table(name="r_s")
public class RS {
    @Id
    @Column(name = "rs_id", columnDefinition = "json")
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;

    @Column(name = "c_x", columnDefinition = "json")
    @Convert(converter = JsonToCxConverter.class)
    private List<Cx> cxs;
    ...
 }

public class Cx {
    private Long someId;
    private List<Long> values;
...    
}
@Converter
public class JsonToCxConverterimplements AttributeConverter<List<Cx>, String>{

   //this gets executed
    @Override
    public String convertToDatabaseColumn(List<Cx> entityAttribute) {
        ObjectMapper objectMapper = new ObjectMapper();
        log.info("--------------------");
        return "";
    }

    @Override
    public List<Cs> convertToEntityAttribute(String dbData) {

   if (dbData == null || dbData.isEmpty()) return Collections.emptyList();
   //... uses the object mapper to parse the json and return a simple object.

   ...

}

Like I said, this happens when calling RSTRepository.findByDuctNameIgnoreCase

CCC
  • 2,427
  • 5
  • 35
  • 54

1 Answers1

1

Yes its really behaving like you are saying. Also when persisting RST, Converter is also called 3x.

It also called 3x when reading just RS entity, i.e. it is not caused by @OneToOne relation.

I think it is how hibernate works. It should not be a problem, you get the right data without error.

From stacktrace I see that second and third call is from AbstractRowReader.performTwoPhaseLoad().

at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.performTwoPhaseLoad(AbstractRowReader.java:241)
at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishUp(AbstractRowReader.java:209)
at org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl.extractResults(ResultSetProcessorImpl.java:133)

I think its something that cannot be disabled. From hibernate sources I see that entity is registered to "hydrating". I found more about it here https://stackoverflow.com/a/29538797/2044957

Another thing: This is happening only when using converter on a collection. Converter is called once if it used on single type, for example AttributeConverter<String, String>.

Peter Šály
  • 2,542
  • 2
  • 10
  • 24