How to map an ArrayList of primitives to a single column?

Ariel Chelsău picture Ariel Chelsău · May 4, 2013 · Viewed 8.7k times · Source

Let's say I have the following situation:

Object Car has an ArrayList of prices, which are all numbers. Is it possible in Hibernate to save all the prices in a single column? I know this violates the first normal form but there might be cases when you don't want them to be saved in a separate table like it's classically done in One-To-Many or Many-To-Many relationships.

In JDO I'd do this easily by saving the ArrayList in a BLOB column.

Some useful related SOF questions: ArrayList of primitive types in Hibernate and Map ArrayList with Hibernate .

Any idea will be highly appreciated!

Answer

Chris March picture Chris March · Mar 15, 2016

I know this is an old question but for anyone trying to do this in a JPA context you can do this

import org.apache.commons.lang3.StringUtils;
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.Collections;

@Converter
public class IntArrayToStringConverter implements AttributeConverter<List<Integer>,String>{
    @Override
    public String convertToDatabaseColumn(List<Integer> attribute) {
        return attribute == null ? null : StringUtils.join(attribute,",");
    }

    @Override
    public List<Integer> convertToEntityAttribute(String dbData) {
        if (StringUtils.isBlank(dbData))
            return Collections.emptyList();

        try (Stream<String> stream = Arrays.stream(dbData.split(","))) {
            return stream.map(Integer::parseInt).collect(Collectors.toList());
        }
    }
}

Then to use it something like this in your entity

@Entity
public class SomeEntity
{

   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private Integer id;

   @Column
   @Convert(converter = IntArrayToStringConverter.class)
   private List<Integer> integers;

   ...
}