如何定义复合主键?

时间:2020-02-24 10:51:46

标签: java mysql spring hibernate jpa

我有数据库表。该表的DDL为:

CREATE TABLE `acsblts` (
  `usrnm` varchar(64) NOT NULL,
  `rl` varchar(64) NOT NULL,
  UNIQUE KEY `acsblts_idx_1` (`usrnm`,`rl`),
  CONSTRAINT `acsblts_ibfk_1` FOREIGN KEY (`usrnm`) REFERENCES `lgn_crdntls` (`usrnm`)
)

现在,我想为此表创建Java类。我所做的是:

@Entity
@Table(name = "acsblts", uniqueConstraints = { @UniqueConstraint(columnNames = { "rl", "usrnm" }) })
public class Acsblts {

    @NotNull
    @Column(name = "rl")
    private String rl;

    @ManyToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.DETACH, CascadeType.REFRESH })
    @JoinColumn(name = "usrnm", nullable = false)
    @JsonIgnore
    private LgnCrdntls usrnm;

    // Constructors, Getters, Setters

}

当我尝试运行该应用程序时,它显示错误:

未为实体指定标识符:com.example.mngmntsstm.entity.user.Acsblts

我了解的是:缺少@Id导致了错误。 如何使用rlusrnm创建组合主键。

使用以下id作为primary_key而不是Composite_primary_key是一个好主意吗?

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;

2 个答案:

答案 0 :(得分:1)

  1. 我认为您情况下最简单的方法是使用composite identifiers with associations
@Entity
@Table(name = "acsblts")
public class Acsblts implements Serializable
{
   @Id
   @Column(name = "rl")
   private String rl;

   @Id
   @ManyToOne
   @JoinColumn(name = "usrnm", nullable = false)
   private LgnCrdntls usrnm;

   public Acsblts()
   {}

   public Acsblts(String rl, String usrnm)
   {
      this.rl = rl;
      this.usrnm = new LgnCrdntls(usrnm);
   }

   // getters, setters

   @Override
   public boolean equals(Object obj)
   {
      if (this == obj) return true;
      if (obj == null || getClass() != obj.getClass() ) return false;

      Acsblts that = (Acsblts) obj;
      return Objects.equals(rl, that.rl) &&
             Objects.equals(usrnm, that.usrnm);
   }

   @Override
   public int hashCode()
   {
      return Objects.hash(rl, usrnm);
   }
}

请注意,由于实体实例与实际标识符之间没有分隔,因此您应该将Acsblts的实例作为primaryKey参数传递给find方法。

Acsblts dat = session.find(Acsblts.class, new Acsblts("CRD2", "RL5"));
  1. 您也可以使用composite identifiers with @EmbeddedId

在这种情况下,您应该通过以下方式声明AcsbltsPK类:

@Embeddable
public class AcsbltsPK implements Serializable
{
   @Column(name = "rl")
   private String rl;

   @ManyToOne
   @JoinColumn(name = "usrnm")
   private LgnCrdntls usrnm;

   @Override
   public boolean equals(Object obj)
   {
      if (this == obj) return true;
      if (obj == null || getClass() != obj.getClass() ) return false;

      AcsbltsPK pk = (AcsbltsPK) obj;
      return Objects.equals(rl, pk.rl) &&
             Objects.equals(usrnm, pk.usrnm);
   }

   @Override
   public int hashCode()
   {
      return Objects.hash(rl, usrnm);
   }
}

然后在Acsblts实体中使用它:

@Entity
@Table(name = "acsblts")
public class Acsblts
{
   @EmbeddedId
   private AcsbltsPK pk;

   // ...
}
  1. 您也可以使用composite identifiers with @IdClass

将以下ID用作primary_key而不是Composite_primary_key是个好主意吗?

您应该为此修改现有的表格。有时,这是不可接受的。

答案 1 :(得分:0)

使用长ID作为主键将有助于由于索引而更快地搜索结果,但是如果您仍要使用主复合键,请参考以下链接,并尝试将其应用于您的问题

https://vladmihalcea.com/the-best-way-to-map-a-composite-primary-key-with-jpa-and-hibernate/

https://www.baeldung.com/jpa-composite-primary-keys