Подтвердить что ты не робот

@embeddable vs @entity для отображения коллекции

Это должно быть довольно наивно, но я сомневаюсь, когда следует использовать @Entity и @Embeddable.

Скажем, у меня есть класс User и Notification.

 @Entity
 public class User{
     //other properties
     @onetomany
     private List<Notification> notifications;
 }

 @Entity
 public class Notification{
     //properties
 }

Я понимаю, что будут таблицы для классов User и Notification, а также третья таблица для сопоставления. Что делать, если я так делаю?

 @Entity
 public class User {
     //other properties
     @ElementCollection
     private List<Notification> notifications;
 }

 @Embeddable
 public class Notification{
     //properties
 }

Я знаю, что это не создаст таблицу для Notification. Но я все еще могу хранить объекты уведомлений. Я просмотрел документацию, но пару сомнений:

  • Это зависит от того, хочу ли я видеть класс B как отдельную таблицу?
  • Есть ли разница в производительности, создающая таблицу и встраиваемый объект?
  • Что я не могу сделать с встраиваемым объектом, который я могу сделать с таблицей, отличной от прямого запроса таблицы?

ПРИМЕЧАНИЯ

Для тех, кто читает этот вопрос, этот question тоже может вам помочь.

4b9b3361

Ответ 1

  • Это зависит от того, хочу ли я видеть класс B как отдельную таблицу?

Да, когда вы используете @Embedded, вы вставляете этот объект @Embeddable в класс @Entity, что позволяет добавлять столбцы для внедренного объекта в ту же таблицу класса @Entity.

  1. Есть ли разница в производительности, создающая таблицу и встраиваемый объект?

Когда вы используете @Embedded, для создания таблицы требуется один запрос, а также для вставки и выбора строки. Но если вы его не используете, требуется несколько запросов, поэтому использование @Embedded дает большую производительность, можно сказать.

  1. Что я не могу сделать с встраиваемым объектом, который я могу сделать с таблицей, отличной от прямого запроса таблицы?

Удаление соответствующего внедренного объекта может быть, но для этого могут быть нарушения ограничений целостности.

Ответ 2

В JPA существует несколько способов создания составных ключевых полей. Давайте посмотрим на метод, используя @Embeddable annotation.
Давайте начнем с класса Entity.

@Entity
@Table
public class TraceRecord {
    @Id
    private TraceRecordPk id;

    @Version
    @Transient
    private int version;

    @Column(columnDefinition = "char")
    private String durationOfCall;

    @Column(columnDefinition = "char")
    private String digitsDialed;

    @Column(columnDefinition = "char")
    private String prefixCalled;

    @Column(columnDefinition = "char")
    private String areaCodeCalled;

    @Column(columnDefinition = "char")
    private String numberCalled;
}

Это довольно простой класс Entity с полями @Id и @Version и несколькими определениями @Column. Не вдаваясь в подробности, вы увидите, что поле @Version также аннотируется @Transient. Я сделал это просто потому, что в моей таблице также нет столбца для отслеживания версий, но моя база данных ведется журналом, поэтому я не слишком беспокоюсь о версировании. Вы также заметите, что поля @Column имеют значение "char", установленное в атрибуте columnDefinition. Это связано с тем, что поля в моей таблице определены как char, а не varchar. Если бы они были varchar, мне не нужно было бы это делать, поскольку по умолчанию String сопоставляет поля varchar.

Поле @Id - это то, что Im заинтересовало прямо сейчас. Это не стандартный Java-тип, а класс Ive. Вот этот класс.

@Embeddable
public class TraceRecordPk implements Serializable {

    private static final long serialVersionUID = 1L;

    @Temporal(TemporalType.DATE)
    @Column
    private Date dateOfCall;

    @Column(columnDefinition="char")
    private String timeOfCall;

    @Column(columnDefinition="char")
    private String callingParty;

    /**
     * Constructor that takes values for all 3 members.
     *
     * @param dateOfCall Date the call was made
     * @param timeOfCall Time the call was made
     * @param callingParty Extension from which the call originated
     */
    public TraceRecordPk(Date dateOfCall, String timeOfCall, String callingParty) {
        this.dateOfCall = dateOfCall;
        this.timeOfCall = timeOfCall;
        this.callingParty = callingParty;
    }
}

Чтобы этот класс мог быть полем @Id в классе Entity, его необходимо аннотировать с помощью @Embeddable, как я упоминал ранее. 3 поля Ive, выбранные для моего составного ключа, являются обычными определениями @Column. Вместо того, чтобы создавать геттеры/сеттеры для каждого поля, Ive просто реализовал конструктор, который принимает значения для всех трех полей, делая любой экземпляр неизменным. При аннотировании класса с помощью @Embeddable этому классу потребуется реализовать Serializable. Итак, Ive добавила по умолчанию serialVersionUID для размещения.

Теперь, когда у вас есть класс, созданный и аннотированный с помощью @Embeddable, теперь вы можете использовать его как тип поля @Id в своем классе Entity. Простой материал.