Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JPA: Saving List of values as comma separated values

I am receiving a simple list of values part of JSON request which I want to save as comma separated values. Tried using following but it did not work.

@Column(nullable = true)
@GeneratedValue(strategy = GenerationType.AUTO)
private ArrayList<String> services = new ArrayList<String>() ;

and

@Column(nullable = true)
@ElementCollection(targetClass = String.class)
private List<String> services = new ArrayList<String>() ;

@ElementCollection threw an exception saying table services does not exist.

like image 560
Himanshu Yadav Avatar asked Nov 06 '15 16:11

Himanshu Yadav


People also ask

How do I persist a list in JPA?

Solution: Since JPA 2.0, you can use an element collection to persist a Collection of value types. You just need to annotate the attribute with @ElementCollection and the persistence provider will persist the elements of the Collection in an additional database table.

How to store List of strings in single Column using jpa?

The easiest way to store list of strings in a single database column is to store them as comma separated strings. We use JPA 2.1 Attribute Converter feature to convert list of string to comma separated string while storing into database and vice versa while reading from the database.

How do I save a list in JPA repository?

In Spring Data JPA Repository is a top-level interface in hierarchy. The saveAll() method has been defined as below. Iterable saveAll(Iterable entities) – used to save multiple entities. The saveAll() method internally annotated with @Transactional.

What is @ElementCollection in JPA?

JPA 2.0 defines an ElementCollection mapping. It is meant to handle several non-standard relationship mappings. An ElementCollection can be used to define a one-to-many relationship to an Embeddable object, or a Basic value (such as a collection of String s).


2 Answers

As mentioned by others in the comments an AttributeConverter works pretty well. This one uses Jackson to serialize as a JSON array. I recommend JSON since it cleanly handles delimiter escaping, nulls, quotes, etc.:

@Converter
public class StringListAttributeConverter implements AttributeConverter<List<String>, String> {

    private static final TypeReference<List<String>> TypeRef = new TypeReference<List<String>>(){};

    @Override
    public String convertToDatabaseColumn (List<String> attribute) {
        if (attribute == null) {
            return null;
        }
        try {
            return ObjectMapperFactory.getInstance().writeValueAsString(attribute);
        }
        catch (IOException ex) {
            throw new UncheckedIOException(ex);
        }
    }

    @Override
    public List<String> convertToEntityAttribute (String dbData) {
        if (dbData == null) {
            return null;
        }
        try {
            return ObjectMapperFactory.getInstance().readValue(dbData, TypeRef);
        }
        catch (IOException ex) {
            throw new UncheckedIOException(ex);
        }
    }
}

I've used this class and it works well in most cases. One caveat I've found is that using this converter can confuse some JPA criteria queries, because it expects a type List on the entity, but finds a String in the db.

like image 193
pedorro Avatar answered Sep 26 '22 11:09

pedorro


The @ElementCollection requires a table to store multiples rows of values,

So you could define as a String column and join/explode in getters and setters, like this

private String services;

public setServices(String services[]) //Can be Array or List
{
     // this.services = Iterate services[] and create a comma separated string or Use ArrayUtils
}

public String[] getServices() //Can be Array or List
{
    // services.split(",") to get a list of Strings, then typecast/parse them to Strings before returning or use Arrays.asList(arguments.split(","));
}
like image 35
Túlio Castro Avatar answered Sep 24 '22 11:09

Túlio Castro