Обект със стойност с OID

Можете ли да опишете предимствата и недостатъците на включването на OID (обикновено идентификатор на ред от база данни) в POJO представляващ обект във вашия модел?

Всъщност не говоря за проблеми, свързани с равенства/хешкод и т.н., трябваше да опиша по-добре моя проблем (моят лош :) )...

Имаме някои от тези класове обекти, които представляват бизнес обекти (като Продукт, Каталог и така нататък...). Понякога те имат „бизнес идентификатор“, например Продуктът може да бъде намерен чрез неговия уникален ProductId (който има 3 полета: идентификатор, тип, хранилище).

В нашата база данни таблицата „Продукт“ има заместваща колона с първичен ключ (OID) в допълнение към 3-те бизнес колони (идентификатор, тип, хранилище), за да улесни препратките към външни ключове и да има по-малко клаузи за присъединяване.

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

productManager.findProductById(ProductId productId);

Въпросът е дали OID трябва или не трябва да бъде включен в продукта или в класа 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 начин е да направите Join. Например с моя 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(). Това нарушава "договора" на Set, както е описано по-горе.

Това е малко ръбов случай, но си струва да се отбележи.

person cliff.meyers    schedule 31.12.2008
comment
Разбира се, прав си, но не това беше смисълът на въпроса ми, съжалявам, че съм твърде пестелив по въпроса... - person Gilles Philippart; 31.12.2008