Наследование в Hibernate

Есть несколько вариантов организации иерархии при работе с Hibernate ORM. На данный момент выделяют три подхода:

  • One table per concrete class - для каждого наследника создается отдельная таблица со всеми полями, включая пронаследованные.
  • One table per class hierarchy - создаем одну "родительскую" таблицу, каждая строка которой должна содержать все поля родительского класса, плюс поля всех наследников, т.е. потенциально кучу null значений.
  • One table per subclass - мэппим базовый класс и наследников на отдельные таблицы и создаем иерархию с помощью внешних ключей.

Остановимся на 3м варианте - One table per subclass, наиболее удачном на мой взгляд, т.к. в базе данных не будет никакой избыточности полей, как в первом варианте, и не будет проблемы масштабирования, как в варианте 2.



Примерная модель базы данных и диаграмма классов
Hibernate Relations fig.1Hibernate Relations fig.1

Класс контейнер
Данный класс содержит список объектов-родителей.

@Entity
@Table(name = "SESSION")
public class Session {
    @Id
    @Column(name = "ID")
    private Integer id;

    @OneToMany(fetch = FetchType.EAGER, mappedBy = "session")
    @Cascade(value = org.hibernate.annotations.CascadeType.ALL)
    private List<Event> events;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public List<Event> getEvents() {
        return events;
    }

    public void setEvents(List<Event> events) {
        this.events = events;
    }
}

Класс-родитель
Данная структура имеет отношение к вышеописанной как ManyToOne (M:1).

@Entity
@Table(name = "EVENT")
@Inheritance(strategy = InheritanceType.JOINED)
public class Event {
    @Id
    @Column(name = "ID")
    private Integer id;

    @ManyToOne
    @JoinColumn(name="SESSION_ID", nullable = false, insertable = true, updatable = true)
    private Session session;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Session getSession() {
        return session;
    }

    public void setSession(Session session) {
        this.session = session;
    }
}

Первый класс-потомок

@Entity
@Table(name = "VIEW_PAGE_EVENT")
@PrimaryKeyJoinColumn(name="ID", referencedColumnName="ID")
public class ViewPageEvent extends Event {
    @Column(name="PAGE_ID")
    private Integer pageId;

    public Integer getPageId() {
        return pageId;
    }

    public void setEditionId(Integer pageId) {
        this.pageId = pageId;
    }
}

Второй класс-потомок

@Entity
@Table(name = "SEARCH_EVENT")
@PrimaryKeyJoinColumn(name="ID", referencedColumnName="ID")
public class SearchEvent extends Event {
    @Column(name = "QUERY")
    private String query;

    public String getQuery() {
        return query;
    }

    public void setQuery(String query) {
        this.query = query;
    }
}

Отправить комментарий

Image CAPTCHA
Enter the characters shown in the image.