JPA предложение модели объекта - PullRequest
1 голос
/ 24 февраля 2012

Я пытаюсь спроектировать модель сущности, используя JPA2.0 через hibernate.

У меня есть домен, подобный этому: есть множество ресторанов, так что, очевидно, есть ресторанная сущность. В каждом ресторане есть несколько различных блюд, которые можно подавать, и 0-ко-многим ресторанам можно подавать одно и то же. Каждое блюдо имеет ряд ингредиентов, а некоторые блюда будут разделять ингредиенты. Каждый ингредиент содержит несколько питательных веществ, и каждый из этих питательных веществ может иметь от 0 до многих ингредиентов.

Я борюсь, потому что я даже не знаю точно, в чем заключается моя проблема, но я знаю, что что-то упустил. Я полагаю, что вопрос заключается в том, как именно реализовать модель предметной области и каковы последствия для первичных ключей и методов .equals / .hashcode.

Первоначально я собирался использовать сгенерированный суррогатный ключ. У каждой сущности будет что-то вроде

@Id
@GeneratedValue
public Long id;

И .equals будет проверять равенство для всех элементов сущностей, кроме id. Например, ресторан будет равен независимо от значения Long id, но равенству его члена List. (и, конечно, Блюдо будет продолжать называть. Равно как и весь путь вниз к питательным веществам.)

Поэтому, когда я даю бобу DAO ресторан, я хочу, чтобы он сохранялся, только если в хранилище данных нет эквивалентных ресторанов (через .equals). Но я предполагаю, что это будет довольно трудоемкий вызов jpql, который я не нахожу элегантным или эффективным (пожалуйста, дайте мне знать, если я ошибаюсь. Я часто ошибаюсь ... смеется). В дальнейшем, если он обнаружит ингредиент, который уже находится в хранилище данных (но является частью блюда, которое не было и, следовательно, вновь сохранилось), он связывает новое блюдо с уже существующим ингредиентом, а не создает совершенно новое (и логически продублированный) ингредиент.

Чем больше я думал об этом, тем болезненнее звучало, что в этой иерархии все выше.

Я начал изучать идею составного ключа (через @IdClass или @EmbeddedId), который сам содержал бы дочерние элементы. Кажется, что сохранить вещи выше в иерархии было бы так же просто, как найти по id и сохранить, если я ничего не найду. Но я очень подозрительно отношусь к этому ... Это не кажется правильным. Это будет означать, что я создаю сущности, в которых все члены и сущности сами и часть составного ключа.

Некоторые вещи на заметку. Есть относительно ограниченное количество питательных веществ. Пространство для ингредиентов - {numOfNutrients} ^ {typesOfNutrients}, которое может быть довольно большим. к тому времени, как мы доберемся до ресторанов, для клиента будет почти невозможно создать дублируемый ресторан по случайности, так как пространство будет действительно большим. Наступает момент, когда мне на самом деле все равно, есть ли дубликат в хранилище данных, потому что это вряд ли произойдет. На самом деле было бы почти интересно посмотреть, произошло ли это. Также не то, что пример ресторана надуман. Мой реальный домен похож по форме.

Извините за бессвязные. Я знаю, что в посте много идей. Но я чувствую, что все они так связаны, я хотел их всех разом поднять.

Может кто-нибудь предложить немного волшебства?

Мне известно об этом сообщении: Класс, который ведет себя как @Entity и @ Embeddable Обычно я вижу что-то вроде: не делайте этого «кроме особых случаев». Это то, что я говорю об одном из этих случаев. Если нет, то какой именно уместно использовать это.

Также обратите внимание, что после помещения ресторана в базу данных его представление является неизменным. Я понимаю, что это нереально с надуманным примером, но это касается моей области. Это заставляет меня думать, что включение всех элементов в составной ключ - это путь ...

1 Ответ

1 голос
/ 24 февраля 2012

Hibernate не использует equals и hashCode, чтобы узнать, является ли объект уже постоянным или нет. Если у объекта есть идентификатор, он является постоянным. Остальное, это ново. И две сущности одинаковы, если они имеют одинаковый идентификатор. Метод equals используется только для сравнения двух отсоединенных объектов или для сравнения открепленных объектов с присоединенным в вашем коде (а не в коде Hibernate).

Вам также нужны equals и hashCode, если сущности хранятся в наборе.

Если вам действительно нужен метод equals и hashCode, использование коллекции дочерних сущностей для их реализации - очень плохая идея. Вам нужно не только загрузить половину базы данных, чтобы иметь возможность вызывать их, но как только вы добавляете ингредиент в блюдо, меняется его hashCode, который «портит» набор, в котором он хранится.

Вы должны использовать неизменяемое неизменяемое уникальное функциональное поле сущности для реализации equals и hashCode (название ресторана, название блюда, название питательного вещества). И обязательно используйте суррогатные идентификаторы. Если у вас нет такого поля, вы можете использовать идентификатор. Но просто убедитесь, что он сгенерирован перед сохранением сущности в наборе.

...