اعمال نشدن ترتیب برای فرزندان یک مدل در هایبرنیت (Hibernate)

۲۸ آذر ۱۳۹۵

پیش از هر چیز باید بگویم که این نوشته مربوط به برنامه‌نویسی در فریم‌ورک اسپرینگ و هایبرنیت است؛ اگر با این فریم‌ورک آشنایی ندارید، خواندن این نوشته‌ی من در مورد این چهارچوب برنامه‌نویسی می‌تواند برای شما مفید باشد. هایبرنیت یک کتابخانه object-relational mapping برای زبان جاوا است که چارچوبی را برای نگاشت یک شی به یک پایگاه داده رابطه‌ای فراهم می‌آورد. در این نوشته قصد داریم مشکل اعمال نشدن ترتیب برای فرزندان یک مدل در هایبرنیت (Hibernate) را بررسی کنیم.



کاربرد اصلی هایبرنیت نگاشت یک کلاس جاوا به یک جدول در پایگاه داده است. هایبرنیت همچنین ابزاری را برای بازیابی داده‌ها فراهم می آورد. هایبرنیت کمک می‌کند یک برنامه نویس بدون استفاده مستقیم از دستورات مربوط به پایگاه داده با آن رابطه برقرار و شی‌ها را بازیابی، ذخیره و یا به روزرسانی کند.

فرض کنید مدلی داریم که رابطه‌ی selfi با خودش داشته و ما نیاز داریم که عناصر مدل را با order یکی از فیلدهای این مدل، fetch کنیم؛ اما مشکلی که وجود دارد این است که عناصر بدون والد (parent = null) با order درست و عناصری که دارای والد هستند با orderی نادرست fetch می‌شوند (به نوعی random order).


class Menu{
       ...
       private Integer      sequence;
       private Set<Menu>    childs;
       private Menu         parent;
       ...
}
 
class MenuViewModel{
       ...
       private Integer               sequence;
       private Set<MenuViewModel>    childs;
       private Long                  parentId;
       ...
}

با اضافه کردن تگ order-by در فایل hbm.xml مدل، مشکل رفع نشد و دوباره order مورد نظر در childها اعمال نمی‌شود:
<set name="childs"  inverse="true" cascade="all"  fetch="select" order-by="sequence">
    <key>
       <column name="parent_id" not-null="false" />
    </key>
    <one-to-many class="org.baharan.cms.model.portlet.menu.Menu" />
</set>

راه حل: با بررسی بیشتر مشخص شد که order  در query مورد نظر لحاظ شده و خروجی آن به صورت صحیح sort شده است؛ بنابراین به نظر می‌رسد که در هنگام مقداردهی Set موجود در ViewModel، آن orderی را که در خروجی query بود نادیده گرفته و مقادیر برحسب محاسبات hash در Set پر می‌شود. برای رفع مشکل، تنها در ViewModel نوع داده‌ای childs را از java.util.Set به java.util.List تغییر داده و order مورد نظرما در childs اعمال شدند.


class Menu{
       ...
       private Integer      sequence;
       private Set<Menu>    childs;
       private Menu         parent;
       ...
}

class MenuViewModel{
       ...
       private Integer               sequence;
       private List<MenuViewModel>    childs; 
       private Long                  parentId;
       ...
}

هیچ نظری موجود نیست: