در ادامه (نمونه پروژه Spring Boot) بخش دوازدهم داریم :

کلاس service بطور خلاصه واسطی جهت سرویس دهی به داده های ارسالی و دریافتی از کلاس Controller و Repository می باشد. در واقع لایه سرویس گذرگاهی بین لایه Controller و Repository می باشدکه وظیفه آن تبدیل نوع Request دریافتی از Controller که در قالب Dto (البته در صورت استفاده ازDesign Pattern Dto,Dao ) است به قالب Dao و بالعکس داده های دریافتی از Repository درقالب Dao و تبدیل آن به Dto برای ارسال به Controller می باشد. برای ایجاد آن ابتدا باید کلاسی برای آن تعریف و بالای آن annotation @Service قرار داده شود. همچنین باید آبجکتی از Repository ایجاد و با قرار دادن annotation @autowired بالای آن می توان آنرا به کلاس Repository متصل نمود. البته می توان بجای استفاده از annotation @autowired , متد سازنده ای که آبجکت ایجاد شده از Repository را بعنوان پارامتر دریافت می کند ایجاد و استفاده نمود که دقیقا کارautowired@ را انجام می دهد . این کلاس واسطی برای ارسال و دریافت داده هاست. همچنین متد هایی که در کلاس Controller ایجاد شده دقیقا در این کلاس هم تعریف شدند با این تفاوت که آنها با آبجکت ایجاد شده از Repository کارمی کنند.

نمونه service بکار رفته با CrudRepository و JpaRepository :

نمونه service بکار رفته با کلاسRepository :

Repository برای ذخیره , بازیابی و جستجوی داده ها کاربرد دارد.به بیان دیگر Repository مکانیزمی جهت کپسوله سازی ذخیره,بازیابی و جستجوی داده ها می باشد.برای ایجاد آن کلاس یا اینترفیسی را تعریف کرده و بالای آن annotation @Repository قرار می گیرد. دو نوع اینترفیس کاربردی جهت کار با داده ها وجود دارد که عبارتند از CrudRepository و JpaRepository که کلاس یا اینترفیس ما می تواند یکی یا هردوی آنها را extends کرده و ازکوئری متد های آماده کاربردی آنها استفاده کند. می توان درون اینترفیس query سفارشی را با قراردادن annotation query@ بالای Query Method ایجاد شده و تعریف کوئری درون annotation query@ از آن استفاده کرد. همچنین بجای استفاده از اینترفیس می توان از روش Jpa data و persistencecontext@ در بالای Repository استفاده نمود که طی آن باید آبجکتی از کلاس Entitymanager ایجاد و در متد های crud ساخته شده آنرا بکار گرفت. بالای متد های crud هم باید Transactional@ استفاده کرد.

در تصویر زیر نمونهRepository ما از نوع Interface بوده که با ارث بری از CrudRepository Interface و تعیین مدل(User ) و نوع فیلد کلید اصلی(که معمولا منظور id است) بعنوان پارامتر جنریک برای آن می توان از متد های آماده CrudRepository مانند save,saveAll,find,findAll,delete,deleteAll در کلاس Service استفاده نمود همانطور که در نمونه تصاویر مربوط به توضیحات کلاس Service آورده شده است.

نمونه اینترفیس CrudRepository :

نمونه اینترفیسJpaRepository که در این پروژه برای Pagination بکار رفته :

نمونه کلاس Repository :

سایر نکات

- <>Iterable : یک اینترفیس است که امکان دسترسی متوالی به عناصر یک مجموعه یا لیست یا غیره را می دهد و وقتی داخل حلقه for قرار می گیرد، تک تک عناصر را جهت کار با آن ها پیمایش کرده و به ما بازمی گرداند.

- <>Optional : این نوع داده مشخص می‌کند که شاید متد مدنظر خروجی نداشته و باید قبل از کاربرد آن، چک کنند که خروجی null نباشد. مثلاً از طریق متد isPresent

- تفاوت GetRefrence و find : متد find موقعی که داده ای در دیتابیس مقداردهی اولیه, استفاده یا توسط entitymanager بارگذاری load نشده باشد بکار رفته و آن داده را از دیتابیس پیدا و باز می گرداند اما متد GetRefrence هنگامی که داده از قبل مقداردهی اولیه یا توسط entitymanager بارگذاری load شده باشد را به ما برمی گرداند که اغلب منظور فیلد primary key یا کلید اصلی تحت عنوان id است که از قبل مقداردهی و load می شوند.همچنین این متد بدون ارتباط مستقیم با دیتابیس می تواند با فیلد مربوطه کار کند.

- برای آپدیت از متد merge (البته با احتیاط چون احتمال به مشکل خوردن هست) در entitymanager استفاده شود.

- متد flush در entitymanager جهت اعمال عملیات بر روی رکورد در صورت وجود آن رکورد از قبل در دیتابیس می باشد اما متد persist با فرض عدم وجود رکورد از قبل در دیتابیس و( برای اولین بار) آنرا به پایگاه داده آورده و ذخیره می کند.

- می توان در متد updateuser کلاس Controller , پارامتر از کلاس dto جهت بهینه سازی کد استفاده کرد و قبل از آن هم باید pathvariable@ ذکر کرد. البته در صورت وقوع مشکل در خروجی گاهی حذف pathvariable@ مانند قطعه کد زیر می تواند مشکل را حل کند.

- Pageable : یک interface جهت صفحه بندی(Pagination) و فرمت دهی به خروجی کاربرد داردکه با آبجکت آن می توان مجموعه ای از تعداد کل صفحات با قابلیت نمایش و فرمت دهی برای هر صفحه دارند را return کرده و با آنها کار کرد.

- PageRequest : کلاسی برای کار با درخواست صفحه بوده که با Pageable آمده و از طریق متد of می توان دو مقدار pagenumber و pagesize را بعنوان پارامتر های آن set نمود.

Stream : می توان برای پیمایش, تبدیل و پر کردن لیست myDAOPage بصورت زیر عمل کرده و لیستی از جنسdto ایجاد شود سپس با استفاده از حلقه foreach نسبت به پیمایش لیست myDAOPage, تبدیل آن به لیست معمولی و dao آن بهdto و در مرحله بعد پر کردن لیست dtolist با داده هایmyDAOPage اقدام نمود اما راه بهینه تر با تعداد کد کمتر هم وجود دارد و آن استفاده از Stream یا جریان داده می باشد که با فراخوانی متد Stream و بعد تعیین نوع مجموعه ای که می خواهیم داده ها در آن ریخته شود (در اینجا نوع مجموعه map انتخاب گردید) امکان پذیر است. همچنین می توان متدی جهت تبدیل جریان dao لیست myDAOPage به dto ایجاد (daoToDto ) و آن را با استفاده از this بعنوان پارامتر map قرار داد. در مرحله بعد بوسیله متد collect امکان جمع آوری و تبدیل جریان به لیست باcollectors.toList وجود دارد.