如何使用JPA/Hibernate设置复合主键的列顺序

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

我在组合主键中的列排序时遇到问题。 我有一个包含以下内容的表:

@Embeddable
public class MessageInfo implements Serializable {

    private byte loc;
    private long epochtime;

    @Column(name = "loc")
    public byte getLoc() {
        return loc;
    }    

    @Column(name = "epochtime")
    public long getEpochtime() {
        return epochtime;
    }
}

在此映射中使用它:

@MappedSuperclass
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class AbstractMessage implements Message {

    private MessageInfo info;
    private int blah;

    @EmbeddedId
    public MessageInfo getInfo() {
        return info;
    }
}

当我使用具体的 @Table 类对 AbstractMessage 进行子类化时,hibernate 创建的数据库和表没有错误。 问题是 hibernate 正在生成复合主键,其中的列顺序与我想要的顺序相反。

CREATE TABLE  `mydb`.`concrete_table` (
  `epochtime` bigint(20) NOT NULL,
  `loc` tinyint(4) NOT NULL,
  `blah` smallint(6) DEFAULT NULL,
  `foo` smallint(6) DEFAULT NULL,
  PRIMARY KEY (`epochtime`,`loc`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

我希望主键是

PRIMARY KEY (`loc`,`epochtime`)

因为我知道我最多有 10 个 loc,但每个 loc 有很多纪元。

如有任何帮助,我们将不胜感激=)

mysql hibernate jpa composite-primary-key
3个回答
12
投票

有一种方法可以做到。 hibernate 如何选择对主键的一组列进行排序是按您定义的对象名称的字母顺序排列的。

例如如果你像这样声明你的对象:

private byte loc;
private long epochtime;

您将得到现在所得到的:

(`epochtime`,`loc`)

但是如果你将它们重命名为例如:

private byte aloc;
private long epochtime;

它将生成它:

(`aloc`, `epochtime`)

a 出现在 e 之前。

这就是当我希望聚集索引按特定顺序排列时我发现的。我知道这很烦人,但这是我能找到的唯一方法,这样我就不必手动更改我的架构。


0
投票

我真的不认为有办法做到这一点。我所能做的就是建议您使用现有的 SQL 创建语句(将其更改为正确的顺序)并在生产中手动运行它。

在测试中让 Hibernate 做它的事情。


0
投票

在 2024 年,使用 Hibernate 6.4.4.Final,您可以简单地按照您选择的顺序使用主键字段在实体上定义唯一索引。然后,Hibernate 在创建表时使用此序列作为其主键约束。

示例:

@Entity
@Table(indexes = {
        @Index(name = "ix_composite_key_entity_second_id_first_id", columnList = "secondId, firstId", unique = true)
})
public class CompositeKeyEntity {

    @Embeddable
    @Data
    public static class Id implements Serializable {
        private UUID firstId;
        private UUID secondId;
    }

    @EmbeddedId
    private final CompositeKeyEntity.Id id = new CompositeKeyEntity.Id();

}

Hibernate 创建的 DDL:

    create table "composite_key_entity" (
        "first_id" uuid not null,
        "second_id" uuid not null,
        primary key ("second_id", "first_id")
    )
© www.soinside.com 2019 - 2024. All rights reserved.