Search code examples
javahibernatejpaspring-data-jpaconverters

Specify particular instance of converter to use in JPA entity instead of class


I have some jpa entity I store in database and it has a field which contains some data in json for example.

@Convert(converter = JsonConverter.class)
public SomeClass entities;

and JsonConverter is smth like:

@Converter(autoApply = true)
public class JsonListConverter implements AttributeConverter<T, String> {

}

What I want to do is to add some constructor to this converter, initialize it with some type(and may be state), and then use it for jpa converting.

So is it possible to specify some particular instance of converter using @Convert annotation(or some other annotation) instead of specifying class?

I want to be able to do this because in different entities I can have different json fields, like array of entities or set, or smth else, so I don't want to write separate converters to cover all cases, because code is the same for all of them, they differ only in generic type and some fields that should be initialized inside before converting.


Solution

  • You can achieve this by writing an abstract class SomeAbstractClass for your entity with equal and hashcode methods implemented. It can also have a property to store the state. Now your concrete implementation SomeClass1 can implement this abstract class and add further details.

    public SomeClass1 extends SomeAbstractClass {
    }
    
    public SomeClass2 extends SomeAbstractClass {
    }
    

    Now for Converter class (implementing AttributeConverter:

    @Converter(autoApply = true)
    public class JsonListConverter implements AttributeConverter<SomeAbstractClass, String> {
        
        @override
        public String convertToDatabaseColumn (SomeAbstractClass sac) {
            // Your implementation goes here
        }
    
        @override
        public SomeAbstractClass convertToEntityAttribute (String s) {
            //check to find if s can be SomeClass1
            if (checkSomeClass1(s)) { 
                // return an instance of SomeClass1
            } else {
                // return an instance of SomeClass2
            }
        }
    }