Хтось може пояснити мені @MapsId
в сплячому режимі? Мені важко це зрозуміти.
Було б чудово, якби це можна було пояснити на прикладі і в яких випадках використання це найбільш застосовне?
Хтось може пояснити мені @MapsId
в сплячому режимі? Мені важко це зрозуміти.
Було б чудово, якби це можна було пояснити на прикладі і в яких випадках використання це найбільш застосовне?
Відповіді:
Ось гарне пояснення від Object DB .
Позначає атрибут взаємозв'язку ManyToOne або OneToOne, який забезпечує відображення первинного ключа EmbeddedId, атрибута в первинному ключі EmbeddedId або простого первинного ключа батьківської сутності. Елемент value визначає атрибут у складеному ключі, якому відповідає атрибут відносини. Якщо первинний ключ сутності має той самий тип Java, що і первинний ключ сутності, на яку посилається відношення, атрибут value не вказується.
// parent entity has simple primary key
@Entity
public class Employee {
@Id long empId;
String name;
...
}
// dependent entity uses EmbeddedId for composite key
@Embeddable
public class DependentId {
String name;
long empid; // corresponds to primary key type of Employee
}
@Entity
public class Dependent {
@EmbeddedId DependentId id;
...
@MapsId("empid") // maps the empid attribute of embedded id
@ManyToOne Employee emp;
}
Прочитайте Документи API тут.
@MapsId
will у рівні збереження (база даних), має лише стовпець первинного ключа. Ідея полягає в тому, щоб поділити первинний ключ між двома сутностями.
Dependent
просто знаючи ідентифікатор Employee
.
Я також знайшов цю примітку корисною: @MapsId
у сплячому режимі анотації відображається стовпець зі стовпцем іншої таблиці.
Він також може використовуватися для спільного використання первинного ключа між 2 таблицями.
Приклад:
@Entity
@Table(name = "TRANSACTION_CANCEL")
public class CancelledTransaction {
@Id
private Long id; // the value in this pk will be the same as the
// transaction line from transaction table to which
// this cancelled transaction is related
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "ID_TRANSACTION", nullable = false)
@MapsId
private Transaction transaction;
....
}
@Entity
@Table(name = "TRANSACTION")
@SequenceGenerator(name = "SQ_TRAN_ID", sequenceName = "SQ_TRAN_ID")
public class Transaction {
@Id
@GeneratedValue(generator = "SQ_TRAN_ID", strategy = GenerationType.SEQUENCE)
@Column(name = "ID_TRANSACTION", nullable = false)
private Long id;
...
}
@MapsId
. Це взагалі має значення?
@Id
і @GeneratedValue
та @Column
), і матиме a @OneToOne
та @JoinColumn
з іншою таблицею, а інша таблиця буде мати @MapsId
. Однак це, мабуть, не спрацювало б, якщо спочатку ВСТАВИТИ в "іншу таблицю".
Як він пояснив Володимиру у своєму підручнику , найкращий спосіб відобразити відносини @OneToOne - це використовувати @MapsId. Таким чином, вам навіть не потрібна двонаправлена асоціація, оскільки ви завжди можете отримати дочірню сутність, використовуючи ідентифікатор батьківської сутності.
IMHO, найкращий спосіб подумати @MapsId
, коли вам потрібно зіставити складений ключ у сутності: m.
Наприклад, клієнт може мати одного або декількох консультантів, а консультант може мати одного або більше клієнтів:
І ваші entites будуть приблизно такими (псевдо-код Java):
@Entity
public class Customer {
@Id
private Integer id;
private String name;
}
@Entity
public class Consultant {
@Id
private Integer id;
private String name;
@OneToMany
private List<CustomerByConsultant> customerByConsultants = new ArrayList<>();
public void add(CustomerByConsultant cbc) {
cbc.setConsultant(this);
this.customerByConsultant.add(cbc);
}
}
@Embeddable
public class ConsultantByConsultantPk implements Serializable {
private Integer customerId;
private Integer consultantId;
}
@Entity
public class ConsultantByConsultant {
@EmbeddedId
private ConsultantByConsultantPk id = new ConsultantByConsultantPk();
@MapsId("customerId")
@JoinColumn(insertable = false, updatable = false)
Customer customer;
@MapsId("consultantId")
@JoinColumn(insertable = false, updatable = false)
Consultant consultant;
}
Склавши цей шлях, JPA автоматично вставляє Customer
та Consultant
ідентифікує EmbeddableId
кожен раз, коли ви зберігаєте консультанта. Тому вам не потрібно створювати файл вручну ConsultantByConsultantPk
.