Home > OS >  Is there a way to get Spring variable substitution inside JPA annotation values?
Is there a way to get Spring variable substitution inside JPA annotation values?

Time:07-05

This works on SQL server:

    @Type(type = "json")
    @Column(columnDefinition = "NVARCHAR(MAX) NULL CHECK(ISJSON(tags) = 1)")
    private List<String> tags = Lists.newArrayList();

But you need to do this on H2:

    @Type(type = "json")
    @Column(columnDefinition = "json")
    private List<String> tags = Lists.newArrayList();

Is there a way to use a spring application property:

#h2
json_coldef=json

#sql server
json_coldef=NVARCHAR(MAX) NULL CHECK(ISJSON(tags) = 1)

so that I can do this?

    @Type(type = "json")
    @Column(columnDefinition = "${json_coldef}")
    private List<String> tags = Lists.newArrayList();

so that it loads it from a spring property specified at JVM system property?

In other words, is there some way I can use spring variables inside the JPA annotation values and get variable substitution?

CodePudding user response:

Answer from comments: No. JPA annotations cannot use spring substitutions.

So you will need to find a way to make sure your annotations are completely dialect independent.

So I went ahead and created this work-around to the issue for now. I will just build my own converter:

    /** This is a database independent way to convert pojo to json to database, then back to
     * pojo from database. There is a better way to do this with {@link com.vladmihalcea.hibernate.type.json.JsonType}, but
     * unfortunately it doesn't work in H2.
     */
    @javax.persistence.Converter
    public static class ListStringConverter implements AttributeConverter<List<String>, String> {

        @Override
        public String convertToDatabaseColumn(List<String> myCustomObject) {
            try {
                return objectMapper.writeValueAsString(myCustomObject);
            } catch (JsonProcessingException e) {
                throw new RuntimeException(e);
            }
        }

        @Override
        public List<String> convertToEntityAttribute(String databaseDataAsJSONString) {
            try {
                return objectMapper.readValue(databaseDataAsJSONString, List.class);
            } catch (JsonProcessingException e) {
                throw new RuntimeException(e);
            }
        }
    }

Then use it:

@Lob
@Convert(converter = ListStringConverter.class)
private List<String> tags = Lists.newArrayList();

It actually performs pretty much the same too. No performance impact that I can tell.

I will remove H2 and replace with testcontainers to make this all moot point.

  • Related