Skip to content

Instantly share code, notes, and snippets.

@miensol
Last active March 22, 2019 08:27
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save miensol/dbb6a47ef21a171fac1d to your computer and use it in GitHub Desktop.
Save miensol/dbb6a47ef21a171fac1d to your computer and use it in GitHub Desktop.
Jpa Json Converter
package sample.json;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import com.google.common.reflect.TypeToken;
import sample.json.Json;
import org.springframework.util.StringUtils;
import javax.annotation.Nonnull;
import javax.persistence.AttributeConverter;
import java.io.IOException;
public abstract class JpaJsonConverter<TAttribute> implements AttributeConverter<TAttribute, String> {
private final TypeToken<TAttribute> type = new TypeToken<TAttribute>(getClass()) {
};
private ObjectReader reader;
@Override
public String convertToDatabaseColumn(TAttribute attribute) {
if (attribute == null) {
return null;
}
try {
return serialize(attribute);
} catch (JsonProcessingException e) {
throw new RuntimeException("cannot serialize attribute " + attribute, e);
}
}
protected String serialize(@Nonnull TAttribute attribute) throws JsonProcessingException {
return mapper().writeValueAsString(attribute);
}
@Nonnull
public ObjectMapper mapper() {
return Json.getMapper();
}
@Override
public TAttribute convertToEntityAttribute(String dbData) {
if (dbData == null || StringUtils.isEmpty(dbData)) {
return valueForEmptyColumn();
}
try {
return deserialize(dbData);
} catch (IOException e) {
throw new RuntimeException("cannot deserialize attribute: " + type + " from: " + dbData, e);
}
}
public TAttribute valueForEmptyColumn() {
return null;
}
protected TAttribute deserialize(@Nonnull String dbData) throws IOException {
ObjectReader reader = getReader();
return reader.readValue(dbData);
}
private ObjectReader getReader() {
//constructing reader takes roughly ~20% deserialization time
ObjectMapper mapper = mapper();
if (reader == null) {
reader = mapper.readerFor(mapper.constructType(type.getType()));
}
return reader;
}
}
package sample.json;
class EntityChild {
String name;
}
class Entity {
@Convert(converter = EntityChildrenListConverter.class)
List<EntityChild> children = new ArrayList<>();
public static class EntityChildrenListConverter extends JpaJsonConverter<List<EntityChild>> {
}
}
@mnatsakanyank
Copy link

Hi, I got to your code because I am having an issue with Jsons we are storing in the columns. Basically I have a question, is it possible to query DB with EntityChild using standard Spring jpa repositories?
e.g repository.findByChildren(List children)

Thank you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment