Есть несколько вариантов организации иерархии при работе с 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.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;
}
}
@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;
}
}
@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;
}
}
@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;
}
}
@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;
}
}

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