我的数据库中有VARCHAR
字段,此字段的值为val1,val2,val3
。
是否可以使用逗号作为拆分分隔符将其设置为实体的ArrayList<String>
属性?
答案 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.Transient
和String
但是你已经管理了这两个字段之间的状态同步{ {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;
}
}