Наследование с помощью Java и гибернации — типизация обновлений

#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:

Это мои выводы:

  1. Нет объективной причины, по которой a Child должен расширяться Parent . С точки зрения моделирования у меня был бы вместо этого один абстрактный класс, давайте вызовем его FamilyMember , а затем Parent , FirstBorn и SecondBorn будет расширяться от члена семейства.
  2. Проблема с понижением качества была бы решена с помощью (1)
  3. Режим гибернации не поддерживает обновление значения дискриминатора. Это означает, что если дочерний элемент достигает совершеннолетия и больше не является дочерним, а родительским. Дочернюю запись необходимо удалить и создать новую запись, соответствующую родительской. Вот как это работает. Дочерний элемент является дочерним до тех пор, пока он больше не перестанет быть дочерним, а затем дочерняя запись удаляется и создается новая, не дочерняя.