#java #hibernate #inheritance #constructor
#java #гибернация #наследование #конструктор
Вопрос:
У меня есть следующая иерархия в моих классах
@Entity
@Table(name = "Parent")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class Parent {
}
@Entity
@DiscriminatorVlaue("FirstChild")
public class FirstChild extends Parent {
}
@Entity
@DiscriminatorVlaue("SecondChild")
public class SecondChild extends Parent {
}
Это создает родительскую таблицу, как и ожидалось.
Некоторая бизнес-логика в моем приложении:
Когда запрос принят, он сохраняется как «родительский» тип и создает следующую запись в таблице
Dtype id value
Parent 1 "some value"
По мере обработки запроса он может быть либо типа FirstChild
, либо типа SecondChild
, поэтому в моем коде где-то у меня есть
if (some condition is met) {
// change the Parent to its firstChild type
}
else {
// chnage it to "SecondChild" type
}
Правильно ли я понимаю и использую наследование? По сути, я перенаправляю объекты в цикл if, который генерирует исключения во время выполнения, но изменяет ли изменение типа объекта также DTYPE
значение в базе данных? По сути, я использую наследование, чтобы упорядочивать вещи по их типам. Есть ли какая-то магия, которую я могу использовать в конструкторах для достижения этого? Но реальный вопрос в том, Dtype
можно ли изменять при обновлении?
Для дальнейшей работы с этим,
Я создал конструкторы в дочерних классах как
public FirstChild(Parent parent) {
id = parent.id
}
но это создает новую строку для подтипов ,
Dtype id value
Parent 1 "some value"
FirstChild 2 "some value"
Я удостоверяюсь, что запись «firstChild» создана с родительским идентификатором (1), но я не уверен, почему создается вторая строка
Комментарии:
1. извините, это была ошибка копирования-вставки, у меня действительно есть столбец DiscriminatorColumn, как и ожидалось, я просто заинтересован в изменении типа при обновлениях
2. Вы не можете, точно так же, как вы не можете изменить тип объекта в Java. Вероятно, вам следует использовать ассоциацию has-a, а не is-a.
3. Итак, какое значение имеет наследование с гибернацией? Это имеет смысл в объектах Java
4. Когда вы пишете
// change the Parent to its firstChild type
, что это значит? Как выглядит ваш код?
Ответ №1:
В реляционных базах данных нет реального наследования. Гибернация просто имитирует это. Наследование — это концепция программирования для использования других классов, таких как owner. Но вы не можете использовать другую таблицу в качестве таблицы-владельца.. В дочерней таблице, если у вас есть элемент, у вас есть родительский элемент, но где родительский элемент? Parent тоже является элементом.. (строка данных). Таким образом, вы имитируете это в базах данных. В Hibernate есть несколько стратегий наследования.’SINGLE_TABLE’ является одной из них и собирает родительскую таблицу и дочерние таблицы в 1 таблицу. Чтобы определить, какой тип является классом, используется ‘DiscriminatorColumn’ в базе данных. Этот столбец не может быть изменен, он статичен и объявлен с вашим классом Java. Вы можете использовать ‘DiscriminatorValue’, чтобы выбрать значение для идентификации класса java в ‘DiscriminatorColumn’. Итак, ваше понимание наследования отличается в реляционных базах данных. Вы должны объявлять данные каждой дочерней строки в строках родительской таблицы…
Ответ №2:
Но реальный вопрос в том, можно ли изменить Dtype при обновлении?
Нет, вы не можете: исходный код.
Из вашего примера ваш чистый Java-код будет выглядеть следующим образом:
Parent parent = new Parent(); //object received from request, stored in database as it is
if (some conditions is met) {
// FirstChild firstChild = (Parent) parent; //this would throw ClassCastException
FirstChild firstChild = new FirstChild(parent); //creating new object, gc will collect parent
}
Таким образом, hibernate действует так же, как java: вы не можете обновить Parent
, вы должны создать новую запись для firstChild
и удалить parent
.
Не было бы полезно использовать @DiscriminatorFormula
вместо проверки some condition is met
при обработке запроса?
@DiscriminatorFormula("case when value = 'some value' then 'FirstChild' else 'SecondChild' end")
Тогда вам не пришлось бы сохранять Parent
и затем обрабатывать его записи.
Ответ №3:
Это мои выводы:
- Нет объективной причины, по которой a
Child
должен расширятьсяParent
. С точки зрения моделирования у меня был бы вместо этого один абстрактный класс, давайте вызовем егоFamilyMember
, а затемParent
,FirstBorn
иSecondBorn
будет расширяться от члена семейства. - Проблема с понижением качества была бы решена с помощью (1)
- Режим гибернации не поддерживает обновление значения дискриминатора. Это означает, что если дочерний элемент достигает совершеннолетия и больше не является дочерним, а родительским. Дочернюю запись необходимо удалить и создать новую запись, соответствующую родительской. Вот как это работает. Дочерний элемент является дочерним до тех пор, пока он больше не перестанет быть дочерним, а затем дочерняя запись удаляется и создается новая, не дочерняя.