Partho63
Partho63

Reputation: 3116

How to define the composite primary keys?

I have database table. DDL for the table is:

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`)
)

Now I want to create Java class for this table. What I have done is:

@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

}

When I try to run the application, it shows the ERROR:

No identifier specified for entity: com.example.mngmntsstm.entity.user.Acsblts

What I understand is: the absence of @Id is causing the ERROR. How can I create a Composite Primary Key using rl and usrnm.

Is it a good idea to use the following id as a primary_key instead of composite_primary_key?

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

Upvotes: 0

Views: 78

Answers (2)

SternK
SternK

Reputation: 13111

  1. I think that the simplest way in your case will be using 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);
   }
}

Please note as there’s no separation between the entity instance and the actual identifier you should pass an instance of Acsblts as the primaryKey parameter to the find method.

Acsblts dat = session.find(Acsblts.class, new Acsblts("CRD2", "RL5"));
  1. You can also use composite identifiers with @EmbeddedId

In this case, you should declare the AcsbltsPK class in the following way:

@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);
   }
}

And then use it in the Acsblts entity:

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

   // ...
}
  1. You can also use composite identifiers with @IdClass.

Is it a good idea to use the following id as a primary_key instead of composite_primary_key?

You should correct your existing sсhema for that. Sometimes, this is not acceptable.

Upvotes: 1

Dinesh Shekhawat
Dinesh Shekhawat

Reputation: 539

Using Long ID as primary key will help to search for results faster due to indexing but if you still want to use primary composite key refer to the following links and try to apply them to your problem

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

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

Upvotes: 0

Related Questions