Объект значения с OID

Можете ли вы описать плюсы и минусы включения OID (обычно это идентификатор строки базы данных) в POJO, представляющий сущность в вашей модели?

На самом деле я не говорю о проблемах, связанных с equals/hashcode и т. д., я должен был лучше описать свою проблему (моя плохая :))...

У нас есть некоторые из этих классов сущностей, которые представляют бизнес-объекты (например, продукт, каталог и т. д.). Иногда у них есть «идентификатор бизнеса», например, продукт можно найти по его уникальному идентификатору продукта (который имеет 3 поля: идентификатор, тип, репозиторий).

В нашей базе данных таблица Product имеет суррогатный столбец первичного ключа (OID) в дополнение к 3 бизнес-столбцам (id, type, репозиторий) для упрощения ссылок на внешние ключи и уменьшения количества предложений соединения.

Классы Product/ProductId являются частью API, который мы предоставляем другим приложениям. Так, например, они могут позвонить:

productManager.findProductById(ProductId productId);

Вопрос в том, следует или не следует включать OID в класс Product или ProductId, зная, что наши клиенты должны использовать идентификатор ProductId.

Плюсы:

  • Я могу использовать OID для другого поиска, например

    Product p = productManager.findProductById(ProductId productId);
    Catalog c = productManager.findAllCatalogsContainingProduct(p.getOid());
    

Мы привыкли много искать в приложении по ProductId, поэтому это экономит каждый раз при обращении к базе данных, чтобы избежать поиска OID, соответствующего ProductId.

Минусы:

  • Я только что показал OID клиенту (будем надеяться, что он не использует его вместо бизнес-ключа!!)

Можете ли вы перечислить другие плюсы и минусы?


person Gilles Philippart    schedule 31.12.2008    source источник


Ответы (2)


Идентификатор строки базы данных = первичный ключ? Если это так, то нет ни плюсов, ни минусов, они должны быть у вас, иначе вы не сможете связать POJO с соответствующей строкой базы данных.

Для извлечения продуктов и каталогов стандартным способом SQL является соединение. Например, с моим DAL я могу сделать:

SearchCriteria sc = new SearchCriteria();
sc.AddBinding("ProductId", productId);
List<Entity> Products = SQL.Read(sc, new Product(new Catalog());

or

List<Entity> Products = SQL.Read(sc, new Catalog(new Product());

Таким образом, нет необходимости сообщать что-либо звонящему или в оба конца.

person Otávio Décio    schedule 31.12.2008

Вы можете столкнуться с проблемами, если ваша реализация equals() или hashCode() основана на идентификаторе, поскольку он, скорее всего, изначально будет нулевым, а затем изменится позже, когда объект будет сохранен. Смотри ниже:

http://java.sun.com/javase/6/docs/api/java/util/Set.html

Примечание. Следует проявлять большую осторожность, если изменяемые объекты используются в качестве элементов набора. Поведение набора не указано, если значение объекта изменяется таким образом, что это влияет на сравнение равенства, в то время как объект является элементом набора. Частный случай этого запрета состоит в том, что множество не может содержать себя как элемент.

Предположим, что ваша реализация hashCode() основана на идентификаторе, а equals() использует hashCode() при сравнении. Если вы добавите объект в набор, а его идентификатор равен нулю, сравнение на равенство будет выполняться одним способом. Если вы затем сохраните объект в наборе, значение его идентификатора, скорее всего, изменится, что изменит поведение equals() и hashCode(). Это нарушает «контракт» Сета, как описано выше.

Это немного пограничный случай, но стоит отметить.

person cliff.meyers    schedule 31.12.2008
comment
Конечно, вы правы, но мой вопрос был не в этом, извините, что я был слишком скуден по этому поводу... - person Gilles Philippart; 31.12.2008