我应该如何覆盖具有复合主键的实体中的 equals/hashCode?
How should I override equals/hashCode in entities with composite primary keys?
我有一个 table,它有一个复合主键,包括它自己的和来自其他 table 的外键。
我决定不使用 @IdClass
或 @EmbeddedId
。
class SomeEntity {
@Id
private String someId;
@Id
@ManyToOne(optional = false)
@JoinColumn(name = ...)
private Other other
// other mappings here
}
Hibernate 会警告这些。
WARN 69752 ... : HHH000038: Composite-id class does not override equals(): ....Some
WARN 69752 ... : HHH000039: Composite-id class does not override hashCode(): ....Some
我如何(应该)实现这两个方法?
我可以(应该)只包含这两个字段吗?其他领域呢?
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Some that = (Some) o;
return Objects.equals(someId, that.someId) &&
Objects.equals(other, that.other);
}
@Override
public int hashCode() {
return Objects.hash(someId, other);
}
I decided not to use an @IdClass
nor @EmbeddedId
.
不得不说这个决定有两个缺点:
想象一下,您有以下实体:
@Entity
@Table(name = "TST_FIRST_ENTITY_EHC")
public class FirstEntity implements Serializable
{
@Id
@Column(name = "fst_id")
private Long id;
@NaturalId
@Column(name = "fst_code")
private String code;
@Id
@ManyToOne(optional = false)
@JoinColumn(name = "fst_sec_id")
private SecondEntity secondEntity;
public FirstEntity()
{
}
public FirstEntity(Long id, Long secId)
{
this.id = id;
secondEntity = new SecondEntity();
secondEntity.setId(secId);
}
// ...
}
要通过 PK 找到这个实体,你应该这样写:
FirstEntity item = session.find(FirstEntity.class, new FirstEntity(1L, 2L));
我呢,看着挺别扭的
至于您的主要问题,您可以使用任何一组字段来标识您的实体。
想象一下,对于上述实体,您具有以下 DDL SQL:
create table TST_FIRST_ENTITY_EHC
(
fst_id bigint,
fst_sec_id bigint,
fst_code varchar(25),
fst_value varchar(500),
primary key (fst_id, fst_sec_id),
unique(fst_code),
foreign key (fst_sec_id) REFERENCES TST_SECOND_ENTITY_EHC(sec_id)
);
您可以根据 id
、secondEntity.id
字段或 code
字段实现实体的 equals
和 hashCode
。基于 natural-id 或 business-key 的方法更可取,因为如果您使用数据库 id 生成,您无法在提交 JPA 事务之前知道实际的 id 值。 (参见 this)。
我有一个 table,它有一个复合主键,包括它自己的和来自其他 table 的外键。
我决定不使用 @IdClass
或 @EmbeddedId
。
class SomeEntity {
@Id
private String someId;
@Id
@ManyToOne(optional = false)
@JoinColumn(name = ...)
private Other other
// other mappings here
}
Hibernate 会警告这些。
WARN 69752 ... : HHH000038: Composite-id class does not override equals(): ....Some
WARN 69752 ... : HHH000039: Composite-id class does not override hashCode(): ....Some
我如何(应该)实现这两个方法?
我可以(应该)只包含这两个字段吗?其他领域呢?
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Some that = (Some) o;
return Objects.equals(someId, that.someId) &&
Objects.equals(other, that.other);
}
@Override
public int hashCode() {
return Objects.hash(someId, other);
}
I decided not to use an
@IdClass
nor@EmbeddedId
.
不得不说这个决定有两个缺点:
想象一下,您有以下实体:
@Entity
@Table(name = "TST_FIRST_ENTITY_EHC")
public class FirstEntity implements Serializable
{
@Id
@Column(name = "fst_id")
private Long id;
@NaturalId
@Column(name = "fst_code")
private String code;
@Id
@ManyToOne(optional = false)
@JoinColumn(name = "fst_sec_id")
private SecondEntity secondEntity;
public FirstEntity()
{
}
public FirstEntity(Long id, Long secId)
{
this.id = id;
secondEntity = new SecondEntity();
secondEntity.setId(secId);
}
// ...
}
要通过 PK 找到这个实体,你应该这样写:
FirstEntity item = session.find(FirstEntity.class, new FirstEntity(1L, 2L));
我呢,看着挺别扭的
至于您的主要问题,您可以使用任何一组字段来标识您的实体。 想象一下,对于上述实体,您具有以下 DDL SQL:
create table TST_FIRST_ENTITY_EHC
(
fst_id bigint,
fst_sec_id bigint,
fst_code varchar(25),
fst_value varchar(500),
primary key (fst_id, fst_sec_id),
unique(fst_code),
foreign key (fst_sec_id) REFERENCES TST_SECOND_ENTITY_EHC(sec_id)
);
您可以根据 id
、secondEntity.id
字段或 code
字段实现实体的 equals
和 hashCode
。基于 natural-id 或 business-key 的方法更可取,因为如果您使用数据库 id 生成,您无法在提交 JPA 事务之前知道实际的 id 值。 (参见 this)。