Reputation: 3116
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
Reputation: 13111
@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"));
@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;
// ...
}
@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
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