我有数据库表。该表的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
导致了错误。 如何使用rl
和usrnm
创建组合主键。
使用以下id
作为primary_key而不是Composite_primary_key是一个好主意吗?
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
答案 0 :(得分:1)
@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"));
在这种情况下,您应该通过以下方式声明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;
// ...
}
将以下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/