Таблицы поиска Hibernate: как отношение объекта или как код / ​​ключ - PullRequest
2 голосов
/ 16 сентября 2011

Итак, я работаю над приложением с множеством связей и таблиц поиска, но все сводится к следующему:

лицо

id INT (PK)
... (name, address, etc)
optcode VARCHAR (FK to Options)
typecode VARCHAR (FK to Types)

Опция

optcode VARCHAR (PK)
optdesc VARCHAR
... (more meta data, like date added, etc)

Типы

code VARCHAR (PK)
desc VARCHAR
... (more meta data, like date added, etc)

Я использую hibernate для доступа к этим таблицам, и, с одной стороны, у Object Relations есть свои преимущества, но с другой стороны, просто использование Strings для кодов работает лучше.

Что лучше, чем объектные отношения против ключей против обоих?

Просто используя ключи:

public class Person {
     private int id;
     ... (more attributes)
     private String optcode;
     private String typecode;
}
In the services:
Person person = new Person();
person.setOptcode("ABC");
person.setTypecode("XYZ");
session.save(person);

Или путь O / R:

public class Person {
     private int id;
     ... (more attributes)
     @JoinColumn
     private Options option;
     @JoinColumn
     private Types type;
}
In the services:
Person person = new Person();
person.setOption(new Options("ABC")); //Assume constructor fills in the 'optcode'
person.setType(new Types("XYZ"));     //Same, with 'code'
session.save(person);

В большинстве случаев постоянства у меня есть только «код», но много раз при отображении данных было бы неплохо показать «desc»

Поскольку у меня будет место для управления объектами Options и Types, они все равно будут существовать, но просто раздражает необходимость заключать «код» в объект.

Как вы думаете, каковы плюсы / минусы разных способов? Что если я просто добавлю оба объекта Person, чтобы я мог использовать то, что более удобно? А как насчет создания сеттеров, которые просто помещают строку в новую сущность Options / Types?

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

Обновление: В результате сущность Person будет иметь почти 20 уникальных отношений сущностей (каждая из которых указывает на отдельную таблицу). Возможно, в веб-интерфейсе будут раскрывающиеся списки, содержащие значения для каждой таблицы. , поэтому я ожидаю, что у меня будет только «код», который можно использовать для сохранения. Related: На самом деле я использую PersonImpl (обычный POJO) и PersonEntity (Hibernate Entity) и Dozer Mapping для перехода между ними.

Ответы [ 4 ]

2 голосов
/ 16 сентября 2011

Смысл ORM в том, чтобы предоставить вам граф объектов, по которому вы можете перемещаться и который отображается в реляционную базу данных.От пользователя вы сможете получить описание его опции, используя person.getOption().getDescription().

. Вы также сможете искать людей с указанной датой выбора, используя

select p from Person p where p.option.date = :date

. Этовозможно только в том случае, если вы сопоставляете внешний ключ как ассоциацию, а не как строку.

Вы не должны использовать new Option(code), чтобы добавить существующую опцию в свою личность.Вместо этого вы должны получить или загрузить опцию из сеанса:

Person p = new Person();
p.setOption((Option) session.load(Option.class, "ABC"));
p.setType((Type) session.load(Type.class, "XYZ"));
session.save(p);

// and now, this code works as expected:
System.out.println(p.getOption().getDescription());
1 голос
/ 16 сентября 2011

Я думаю, что сущностные отношения облегчают ваше кодирование, вообще говоря, особенно при запросе объектов: что проще, чем сказать person.getOption (). GetDescription ()?Однако у этого подхода есть недостатки:

  • Ссылочные объекты должны быть загружены из БД, особенно если у вас есть каскад сохранения.В save-cascade, как вы, наверное, знаете, Hibernate будет жаловаться, что объект существует в БД.Я не уверен, что происходит, когда у вас нет каскада сохранения.
  • Ссылочные объекты должны загружаться либо отдельным запросом, либо внешним соединением при загрузке основного объекта. Может вызвать проблемы с производительностью.

Сохранение ключей в виде простых свойств может помочь в случаях сложных отношений, например, при ссылке на сущность big с большой нагрузкойдолжно быть сделано Hibernate.Такой подход может облегчить загрузку «главной» сущности для системы.Это означает, что вам придется выполнить загрузку объекта самостоятельно, если вам нужны его свойства.Я бы сказал, что для неизменяемых сущностей типа «поиск», вы можете безопасно хранить в памяти Map их экземпляров и получать () их по ключу, вместо того, чтобы идти в БД.Недостатком является то, что вы разделите свою логику обработки сущностей: вам нужно будет помнить, какие сущности кэшировать и управлять их кешами.

Я бы сказал, что в общем случае всегда лучше работать ссущности, которая является вашей моделью в конце концов.Hibernate настаивает на том, что он помогает вам сохранить вашу объектную модель, чтобы помочь вам.Вполне логично делегировать столько же ресурсов персистентности в Hibernate.Однако являются случаями, когда Hibernate не может очень хорошо справиться с «правильной» моделью: сущностями со многими отношениями, «горячими» сущностями, которые используются постоянно и т. Д. В этих случаях, если HibernateМеханизмы не могут помочь (кэш 2-го уровня, например), вам действительно нужно прибегнуть к таким «хитростям» и выполнить часть работы самостоятельно.

0 голосов
/ 05 января 2012

Я столкнулся с этим вопросом, потому что мне было интересно, что делают люди, когда сталкиваются с сущностями, которые требуют поиска других сущностей. Основная проблема заключается в том, что вы больше не можете просто создать экземпляр, даже в тесте. Мой предпочтительный подход - перейти на Фабрику или на внешний (например, не статический класс) Строитель.

Проблема, с которой я столкнулся в целом, заключается в том, что она очень проста, и в ней задействовано много подверженных ошибкам шаблонов. Например, предположим, что у меня есть фрагмент содержимого, называемый Listing, и я должен отследить источник, из которого он пришел (где я его нашел). Источник - очень простая сущность, но теперь, когда у меня есть ссылка на него внутри Листинга, я больше не могу создавать Листинги, не выполняя поиск источника и затем вставляя соответствующий.

Было бы целесообразно, если возможно, обрабатывать это с помощью простых аннотаций, например что-то вроде mappedBy, но ссылаясь либо на id, либо на имя, а затем контейнер может выполнить поиск и внедрение.

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

0 голосов
/ 21 сентября 2011

Полагаю, я просто буду использовать @MappedSuperclass Hibernate для случаев, когда у таблиц много одинаковой структуры («код», «описание» и т. Д.), Чтобы можно было уменьшить количество строк кода.Но в противном случае O / R, кажется, путь.

...