将实体中的列表转换为数据库中的单个字符串列

时间:2015-12-02 17:18:47

标签: string hibernate arraylist

我的数据库中有VARCHAR字段,此字段的值为val1,val2,val3

是否可以使用逗号作为拆分分隔符将其设置为实体的ArrayList<String>属性?

4 个答案:

答案 0 :(得分:57)

如果您使用JPA 2.1,则可以创建@Converter public class StringListConverter implements AttributeConverter<List<String>, String> { @Override public String convertToDatabaseColumn(List<String> list) { // Java 8 return String.join(",", list); // Guava return Joiner.on(',').join(list); } @Override public List<String> convertToEntityAttribute(String joined) { return new ArrayList<>(Arrays.asList(joined.split(","))); } }

@Column
@Convert(converter = StringListConverter.class)
private List<String> strings;

您可以在实体中使用此转换器:

@Entity
private MyEntity {
  ...
  private String strings;

  public List<String> getStrings() {
    return Arrays.asList(strings.split(","));
  }

  public void setStrings(List<String> list) {
    strings = String.join(",", list);
  }
}

在JPA 2.1之前,您可以手动执行此操作:

Arrays.asList

我将ArrayList包装在转换器的Arrays.asList中,因为结果存储在属性中,对该列表的任何更改都将写回数据库 - 因此我需要一个可更改的列表(我无法在CheckTimer())的结果中添加任何内容。在2.1 解决方案之前的中,结果与属性无关,并且可更改列表不会与属性同步。

要查询包含此类属性中特定项目的实体,请参阅我的回答here

答案 1 :(得分:5)

是的,这是可能的。

使用Hibernate 4.3.x +你可以定义一个AttributeConverter,虽然我很确定这对早期的Hibernate版本不起作用,因为List类型。请参阅此示例:http://www.thoughts-on-java.org/jpa-21-how-to-implement-type-converter/

实现此功能的另一种方法是实现自定义UserType并使用org.hibernate.annotations.Type注释字段/ getter。以下是一个很好的例子:http://blog.xebia.com/understanding-and-writing-hibernate-user-types/

JPA兼容的另一种方式是有两个字段,List注释javax.persistence.TransientString但是你已经管理了这两个字段之间的状态同步{ {1}}和PrePersist听众自己。这是一个使用监听器的示例:http://alexandregama.org/2014/03/23/entity-listeners-and-callback-methods-jpa/

答案 2 :(得分:1)

尝试使用@ElementCollection和@CollectionTable批注

答案 3 :(得分:0)

如果您希望 String 中有逗号,那么 split()/join() 是不够的。对于那些寻找更好/不同解决方案的人,这里是 - 通过序列化为 JSON 并从 JSON 反序列化。缺点是数据库中使用的字符较多,但它适用于您可以拥有的大部分文本。

package ...;

import java.io.Serializable;
import javax.persistence.AttributeConverter;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class StringArrayConverter implements AttributeConverter<String[], String>, Serializable {

    private static final long serialVersionUID = -2744576922911393664L;

    @Override
    public String convertToDatabaseColumn(final String[] attribute) {
        try {
            return new ObjectMapper().writeValueAsString(attribute);
        }
        catch (@SuppressWarnings("unused") final JsonProcessingException e) {
            // ignore
        }
        return null;
    }

    @Override
    public String[] convertToEntityAttribute(final String dbData) {
        try {
            return new ObjectMapper().readValue(dbData, String[].class);
        }
        catch (@SuppressWarnings("unused") final JsonProcessingException e) {
            // ignore
        }
        return null;
    }

}

用法示例: import java.io.Serializable; import javax.persistence.AttributeConverter; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; public class StringArrayConverter implements AttributeConverter<String[], String>, Serializable { private static final long serialVersionUID = -2744576922911393664L; @Override public String convertToDatabaseColumn(final String[] attribute) { try { return new ObjectMapper().writeValueAsString(attribute); } catch (@SuppressWarnings("unused") final JsonProcessingException e) { // ignore } return null; } @Override public String[] convertToEntityAttribute(final String dbData) { try { return new ObjectMapper().readValue(dbData, String[].class); } catch (@SuppressWarnings("unused") final JsonProcessingException e) { // ignore } return null; } }