迁移到 Hibernate 6:持久化 ArrayList

问题描述 投票:0回答:1

我有以下实体定义:

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')
  1. 使用 Hibernate 持久保存此类 ArrayList 的正确方法是什么?
  2. 如何确保以前以这种方式存储的数据仍然可以访问并且与新的数据存储方式兼容?
hibernate spring-data-jpa
1个回答
0
投票

不确定这是否是最好的方法,但显然在 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;
© www.soinside.com 2019 - 2024. All rights reserved.