Полиморфизм объектов гибернации с использованием аннотации @MappedSuperclass

#java #hibernate #jpa #orm #hibernate-mapping

#java #гибернация #jpa #orm #гибернация-отображение

Вопрос:

Рассмотрим следующую модель:

Абстрактный класс AbstractLog

 @MappedSuperclass
public abstract class AbstractLog{

    private Long id;
    private Set<Comment> comments;

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "quasar_log_id_seq")
    public Long getId() {
        return id;
    }

    @OrderBy(clause = "created")
    @OneToMany(mappedBy = "abstractLog", fetch = FetchType.LAZY, cascade = { CascadeType.ALL }, orphanRemoval = true)
    public Set<Comment> getComments() {
        return comments;
    }

    // setters
}
  

Журнал аудита

 @Entity
@SequenceGenerator(name = "quasar_log_id_seq", sequenceName = "quasar_log_id_seq")
public class AuditLog extends AbstractLog {

    private Set<AuditLogItem> items;

    @OrderBy(clause = "date")
    @OneToMany(mappedBy = "auditLog")
    public Set<AuditLogItem> getItems() {
        return items;
    }
}
  

Журнал документации

 @Entity
@SequenceGenerator(name = "quasar_log_id_seq", sequenceName = "quasar_log_id_seq")
public class DocumentationLog extends AbstractLog {

    private Set<DocumentationLogItem> items;

    @OrderBy(clause = "date")
    @OneToMany(mappedBy = "documentationLog")
    public Set<DocumentationLogItem> getItems() {
        return items;
    }

}
  

Комментарий

 @Entity
@SequenceGenerator(name = "quasar_comment_id_seq", sequenceName = "quasar_comment_id_seq", initialValue = 1, allocationSize =1)
@Table(name = "quasar_comment")
public class Comment extends IdentifiableEntity {

    private User user;
    private String comment;
    private AbstractLog abstractLog;

    @Id
    @Override
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "quasar_comment_id_seq")
    public Long getId() {
        return super.getId();
    }

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "id_user")
    public User getUser() {
        return user;
    }

    @Column(name = "comment", length = 300)
    public String getComment() {
        return comment;
    }


    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "audit_log_id", nullable = false)
    public AbstractLog getAbstractLog() {
        return abstractLog;
    }

}
  

Вы заметите, что генератор последовательности идентификаторов одинаков для всех расширенных объектов AbstractLog .

Цель состоит в том, чтобы объект Comment был общим для всех расширенных объектов AbstractLog . Возможно ли это с помощью аннотации @MappedSuperclass ? Если бы я использовал @Inheritance аннотацию, класс AbstractLog тоже был бы создан, но я этого не хочу. В настоящее время выдается ссылка на ошибку неизвестного объекта.

Ответ №1:

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

Если вы не хотите, чтобы базовый класс был отдельной таблицей (например, таблица для каждого подкласса), вы можете использовать стратегию таблица для конкретного класса. У каждого объекта будет своя таблица, а унаследованные свойства будут удобны только для Java, поскольку они будут дублироваться в каждой таблице SQL.

Таким образом, вы можете заменить @MappedSuperclass на:

 @Inheritance(InheritanceType.TABLE_PER_CLASS)
  

Но согласно Java Persistence wiki:

По умолчанию используется наследование одной таблицы, а таблица для каждого класса является необязательной функцией спецификации JPA, поэтому не все поставщики могут ее поддерживать.

Hibernate поддерживает его, но если вы планируете использовать другого поставщика JPA, у вас может не быть его поддержки.