我有以下实体定义:
import java.io.Serializable;
import java.time.ZonedDateTime;
import java.util.ArrayList;
@Getter
@Setter
@Entity(name = "trackgeodata")
@Table(name = "trackgeodata")
public class TrackGeodata implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Lob
@Column(name = "times")
private ArrayList<ZonedDateTime[]> times;
@Lob
@Column(name = "altitudes")
private ArrayList<int[]> altitudes;
}
所以基本上将 ZonedDateTime 和 int 的 ArrayList 存储为 @Lob。这个效果很好。
现在,在尝试迁移到 Spring Boot 3.2 和 Hibernate 6 时,我遇到以下错误:
class org.hibernate.type.internal.BasicTypeImpl cannot be cast to class org.hibernate.type.BasicPluralType (org.hibernate.type.internal.BasicTypeImpl and org.hibernate.type.BasicPluralType are in unnamed module of loader 'app')
不确定这是否是最好的方法,但显然在 Hibernate 6 中你需要更加明确地了解这些类型的转换/投影。
最后,我为两个 ArrayList 编写了一个自定义的 AttributeConverter:
@Converter
public static class TimesTypeConverter implements AttributeConverter<ArrayList<ZonedDateTime[]>, byte[]> {
@Override
public byte[] convertToDatabaseColumn(ArrayList<ZonedDateTime[]> attribute) {
if (attribute == null) {
return null;
}
return serializeObject(attribute);
}
@Override
public ArrayList<ZonedDateTime[]> convertToEntityAttribute(byte[] dbData) {
if (dbData == null) {
return null;
}
return (ArrayList<ZonedDateTime[]>) deserializeObject(dbData);
}
private static byte[] serializeObject(Object obj) {
try (ByteArrayOutputStream b = new ByteArrayOutputStream();
ObjectOutputStream o = new ObjectOutputStream(b)) {
o.writeObject(obj);
return b.toByteArray();
} catch (IOException e) {
throw new RuntimeException("Serialization error", e);
}
}
// Utility method for deserialization
private static Object deserializeObject(byte[] bytes) {
try (ByteArrayInputStream b = new ByteArrayInputStream(bytes);
ObjectInputStream o = new ObjectInputStream(b)) {
return o.readObject();
} catch (IOException | ClassNotFoundException e) {
throw new RuntimeException("Deserialization error", e);
}
}
}
并将转换器分配给该字段:
@Lob
@Convert(converter = TimesTypeConverter.class)
@Column(name = "times")
private ArrayList<ZonedDateTime[]> times;