NHibernate ja objektide hierarhia lugemine
30.08.2008 | Gunnar
Tegin väikse katse NHibernate-iga ja proovisin ta panna välja pumpama andmeid hierarhilisest tabelist. Muideks, tahame me seda või mitte, valdav osa meie igapäevaseid andmeid on ühel või teisel moel hierarhilised. Me lihtsalt leiame alati häid nõkse kuidas andmete hierarhilist loomust vältida või osavalt ümber mängida. Alati see aga ei õnnestu ja seepärast võib ka mu pisike eraviisiline eksperiment ehk teistelegi progejatele huvitav tunduda.
Ma ei hakka oma katse tausta pikemalt selgitama, sest antud katse ei hõlmanud ühte konkreetset juhtumit. Minu huvi oli see, et leida küsimusele vastus ja võimalusel kasutada seda vastust kõikides sarnastes olukordades.
Hierarhiline tabel
Aga asja juurde. Alustuseks olgu meil üks tabel, mis sisaldab hierarhilisi andmeid. Õigemini, see on fragment tabelist, aga see-eest kõike vajalikku sisaldav fragment.
Tabeli primaarvõti on tavaline int tüüpi väli, parent_id on samuti int tüüpi, kui erinevalt primaarvõtmest võib see sisaldada ka väärtust NULL. Seda on vaja esimese taseme ridade korral, sest need ei allu ühelegi reale.
Hierarhiline klass
Tabelile vastav klass pole kuigi erinev sellest, mis tabelis näeme.
{
public virtual int Id { get; internal set; }
public virtual decimal Amount { get; set; }
public virtual IList<PriceOfferingTemplateLine> ChildItems { get; internal set; }
public virtual string Description { get; set; }
public virtual string Title { get; set; }
}
Klassil on alluvate objektide jaoks defineeritud automaatne omadus nimega ChildItems. Midagi rohkemat meil seoses hierarhia hoidmisega vaja ei lähe.
Mapping
Mapping, mida me andmebaasist hierarhiate kohale toomiseks kasutame, on järgmine.
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class
name="Test.PriceOfferingTemplateLine, Test"
table="price_offering_template_item">
<id name="Id" column="price_offering_template_item_id" type="Int32" unsaved-value="0">
<generator class="identity" />
</id>
<property name="Amount" column="amount" type="Decimal" />
<property name="Description" column="description" type="String" />
<property name="Title" column="title" type="String" />
<bag name="ChildItems" table="price_offering_template_item" where="parent_id is not null">
<key column="parent_id"></key>
<one-to-many class="Test.PriceOfferingTemplateLine, Test" />
</bag>
</class>
</hibernate-mapping>
Nagu näeme on tegemist küllaltki lihtsa ühesuunalise mappinguga. Ja sellega tuleb NHibernate kenasti toime. Hierarhia muutmiseja kustutamise juurde pöördun tagasi siis, kui kellelgi see küsimus peaks tõstatuma ja seega oleks põhjust jälle sel teemal kirjutamiseks.

01.09.2008 kell 02:12
where=”parent_id is not null” on üleliigne
01.09.2008 kell 02:14
PS: ühtlasi soovitaks baastüüpidel (decimal, string jne) tüüpi mäpingufailis spetsifitseerida, arvuti on rauast asi, las teeb tööd ja mõtleb ise välja. Pärast lihtsam ka koodi muutustega toime tulla.
01.09.2008 kell 02:15
“mitte spetifitseerida”. tund hiline.
01.09.2008 kell 08:48
Jah, see where peab kuuluma tegelt selle objekti bagile, mis esimese leveli ridu siintoodud klassist hoiab. Jälle kord õnnestus mul ennast kopi-peisti gängsterina tõestada, kuid parandusi ei saa ka teha, sest muidu ei saa teised lugejad aru, millest me siin kommentaarides nüüd rääkisime.