PDA

View Full Version : حرفه ای: لوپ بینهایت در jackson json Many-to-Many و hibernate



ahmad.mo74
پنج شنبه 06 شهریور 1393, 19:12 عصر
سلام، فرض کنید ما یه کلاس داریم به اسم User که دارای فیلد های id, username, email,... و یک مجموعه ای از دوستان یعنی مثلا Collection<User> friends که تو هایبرنت باید ManyToMany باشه و بقیه داستان ها...
حالا ما این آبجکت رو از دیتابیس گرفتیم و میخوایم به json تبدیل کنیم...اما یک مشکلی هست که فکر میکنم اکثرا قبلا باهاش برخورد داشتید یعنی وقتی این آبجکت میخواد به json تبدیل بشه تو لوپ بینهایت گیر میکنه چون هر User یه مجموعه ای از User ها داره و دوباره هر کدوم اون مجموعه رو دادن و الی آخر...و راههای مختلفی هم برای هندل کردنش وجود داره مثل استفاده از @JsonIgnore که به درد ما نمیخوره چون ما اون مجموعه رو میخوایم...
یه راه دیگه اینه که برای هر یوزر یک id به خصوصی تعریف کنیم که json تشخیص بده آبجکت ها رو و هرکدوم رو دوباره ذخیره نکنه مثلا: (این راه جواب میده و مشکلی نیست اما من دنبال راه بهتری هستم)
@JsonIdentityInfo(generator = ObjectIdGenerators.UUIDGenerator.class, property = "@UUID")
public class User{
...
}
اما این روش هم خیلی مطلوب نیست چون یک فیلد اضافه میشه به هر آبجکت ولی ما میخوایم هر آبجکت همونتوری که هست به json تبدیل بشه...
یه روش دیگه هم اینه که از این (https://github.com/FasterXML/jackson-datatype-hibernate) استفاده کنیم ولی باز هم کار نمیکنه و تو لوپ میفته...

خب، دوستان نظر شما چیه؟ اگر تجربه همچین مشکلی رو دارید و تونستید برطرف کنید لطفا راهنمایی کنید.

cups_of_java
پنج شنبه 06 شهریور 1393, 20:57 عصر
http://keenformatics.blogspot.com/2013/08/how-to-solve-json-infinite-recursion.html

http://stackoverflow.com/questions/3325387/infinite-recursion-with-jackson-json-and-hibernate-jpa-issue

ahmad.mo74
پنج شنبه 06 شهریور 1393, 21:08 عصر
ممنون، لینک اول خوب بود ولی لینک دوم همون JsonIgnore@ رو پیشنهاد داده...
به نظرم همون راه دوم یعنی نسبت دادن یه uid به هر آبجکت یا همون alias کردن که تو لینک اولم بهش اشاره شده بهترین و منطقی ترین راهه چون واقعا چاره دیگه ای جز این کار نیست چون هر آبجکت ممکنه 100 جای دیگه هم باشه و مجبوریم از alias اش استفاده کنیم... ولی گفتم این سوالو مطرح کنم شاید دوستان راه بهتری هم بلد باشن...بازم ممنون

ahmad.mo74
پنج شنبه 06 شهریور 1393, 21:16 عصر
البته یک راه دیگه هم هست...اصلا ما چرا همون آبجکت user رو json کنیم؟ میشه به جاش یه کلاس دیگه ای تعریف کنیم که همون فیلد هارو داشته باشه ولی به جای Collection <User> friends یک مجموعه ای از id هارو توش داشته باشه یعنی Collection <long> friendsId که ما با همون id ها هم میتونیم آبجکت اصلی رو فراخونی کنیم...

omidbizdotcom
یک شنبه 16 شهریور 1393, 13:39 عصر
سلام، فرض کنید ما یه کلاس داریم به اسم User که دارای فیلد های id, username, email,... و یک مجموعه ای از دوستان یعنی مثلا Collection<User> friends که تو هایبرنت باید ManyToMany باشه و بقیه داستان ها...
حالا ما این آبجکت رو از دیتابیس گرفتیم و میخوایم به json تبدیل کنیم...اما یک مشکلی هست که فکر میکنم اکثرا قبلا باهاش برخورد داشتید یعنی وقتی این آبجکت میخواد به json تبدیل بشه تو لوپ بینهایت گیر میکنه چون هر User یه مجموعه ای از User ها داره و دوباره هر کدوم اون مجموعه رو دادن و الی آخر...و راههای مختلفی هم برای هندل کردنش وجود داره مثل استفاده از @JsonIgnore که به درد ما نمیخوره چون ما اون مجموعه رو میخوایم...
یه راه دیگه اینه که برای هر یوزر یک id به خصوصی تعریف کنیم که json تشخیص بده آبجکت ها رو و هرکدوم رو دوباره ذخیره نکنه مثلا: (این راه جواب میده و مشکلی نیست اما من دنبال راه بهتری هستم)
@JsonIdentityInfo(generator = ObjectIdGenerators.UUIDGenerator.class, property = "@UUID")
public class User{
...
}
اما این روش هم خیلی مطلوب نیست چون یک فیلد اضافه میشه به هر آبجکت ولی ما میخوایم هر آبجکت همونتوری که هست به json تبدیل بشه...
یه روش دیگه هم اینه که از این (https://github.com/FasterXML/jackson-datatype-hibernate) استفاده کنیم ولی باز هم کار نمیکنه و تو لوپ میفته...

خب، دوستان نظر شما چیه؟ اگر تجربه همچین مشکلی رو دارید و تونستید برطرف کنید لطفا راهنمایی کنید.

من برای اینکار یه لایبری کوچک دارم اگه خواستی می تونی به جای jackson ازش استفاده کنی اگه اون فیلتر و اضافه کنی بهش خودش ریکرژن و می فهمه و سریالایز نمی کنه



https://github.com/omidp/axon
Axon axon = new AxonBuilder().addFilter(new RecursionControlFilter()).create();
axon.toJson(obj);