Я решил не использовать ни @IdClass
, ни @EmbeddedId
.
Я должен сказать, что это решение имеет два недостатка:
- Это подход не разрешен спецификацией JPA, поэтому это решение для спящего режима c. (См. this )
- Нет разделения между экземпляром объекта и фактическим идентификатором. Чтобы запросить эту сущность, в контекст персистентности должен быть передан экземпляр самой сущности. (См. this )
Представьте, у вас есть следующая сущность:
@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)
);
Вы можете реализовать equals
и hashCode
своей сущности на основе полей id
, secondEntity.id
или на основе поля code
. Подход, основанный на естественном идентификаторе или бизнес-ключе, является предпочтительным, потому что, если вы используете генерацию идентификатора базы данных, вы не можете знать фактические значения идентификатора до того, как транзакция JPA будет зафиксирована. (См. это ).