使用 JPA/Hibernate 将 BigDecimal[][] 保存到 MySQL 数据库

Persisting BigDecimal[][] to MySQL database by using JPA/Hibernate

我需要使用 Hibernate 将 BigDecimal[][] 类型保存到 MySQL 数据库。我不知道该怎么做。我试过这个:

   @Getter
@Setter
@ToString
@RequiredArgsConstructor
@Embeddable
@TypeDef(name = "coordinates_array",
         typeClass = BigDecimalArrayType.class)
public class Geometry {
    private String type;
    @Type(
            type = "coordinates_array",
            parameters = @org.hibernate.annotations.Parameter(
                    name = "sql_array_type",
                    value = "BigDecimal"

            )
    )
    @Column(
            name = "coordinates",
            columnDefinition = "BigDecimal[][]"
    )
    BigDecimal[][] coordinates;}

没有 BigDecimalArrayType class。我如何定义 BigDecimalArrayType?或者有什么可以替代的吗?

也许你可以将 BigDecimal[][] 转换成一个 blob,如果你想保持原样,而不是将 rows/columns 分解到适当的表中。

如我的评论所述,由于您不想以“纯文本”方式保存数组,您可以按照这种方式进行操作。

使用两个字段,一个是持久的(数据库的一部分),另一个是暂时的(仅是应用程序逻辑的一部分)。 持久性将是您的 CoordinateHolderbyte[],短暂性将是 BigDecimal[][].

这里是CoordinateHolder的class。如您所见,我正在使用 @Transient 来禁止保留字段。

@Embeddable
public class CoordinateHolder implements Serializable
{
    @Transient
    private BigDecimal[][] transientCoordinates; // Will not be saved in the DB, is part only of the business logic.

    public BigDecimal[][] getTransientCoordinates()
    {
        return transientCoordinates;
    }

    public void setTransientCoordinates(BigDecimal[][] transientCoordinates)
    {
        this.transientCoordinates = transientCoordinates;
    }
}

这之后让我们来看看实体 class:

@Entity(name = "test_name")
public class TestEntity
{
    // Your id...
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;


    @Embedded
    private CoordinateHolder coordinateHolder;

    @Lob
    @Column(name = "coordinates", columnDefinition = "BLOB")
    private byte[] blobCoordinates;

    public void setCoordinates(BigDecimal[][] arr)
    {
        if (coordinateHolder == null)
        {
            coordinateHolder = new CoordinateHolder();
        }
        coordinateHolder.setTransientCoordinates(arr);
    }

    public BigDecimal[][] getCoordinates()
    {
        if (coordinateHolder == null)
        {
            return null;
        }

        return coordinateHolder.getTransientCoordinates();
    }


    // This can also be done through Entity listeners which actually do the same thing

    // Pre persist is always performed before persisting this entity
    @PrePersist
    public void prePersisting()
    {
        System.out.println("Hey I am being persisted. And now I am turning my transient coordinates into BLOB for the db");

        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream out;
        try
        {
            out = new ObjectOutputStream(bos);
            out.writeObject(coordinateHolder);
            out.flush();
            blobCoordinates = bos.toByteArray();
        } catch (Exception e)
        {
            // Do smth with your exception...
            e.printStackTrace();
        } finally
        {
            try
            {
                bos.close();
            } catch (IOException ignored)
            {
                // ignore close exception
            }
        }
    }

    // Perform after loading...
    @PostLoad
    public void postLoading()
    {
        System.out.println("Hey I am being fetched, I am turning my BLOB into the array holder so that you can use it in your app");

        ByteArrayInputStream bis = new ByteArrayInputStream(this.getBlobCoordinates());
        ObjectInput in = null;
        try
        {
            in = new ObjectInputStream(bis);
            CoordinateHolder o = (CoordinateHolder) in.readObject();

            this.setCoordinateHolder(o);
        }
        catch (Exception e)
        {
            // Do smth with your exception...
            e.printStackTrace();
        }
        finally
        {
            try
            {
                if (in != null)
                {
                    in.close();
                }
            } catch (IOException ex)
            {
                // ignore close exception
            }
        }

    }
    ... Further getters and setters...
}

代码有注释说明,应该可以看懂。这使您可以坚持您所需要的。