<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>پست‌های انتشارات نشریه دایکه</title>
        <link>https://virgool.io/dayche-group-Blog/feed</link>
        <description>نشریه دایکه محلی هست برای معرفی و ارائه مقالات جذاب و مفید در حوزه های مرتبط با علوم داده و ابزارهای تحلیل و پیاده سازی و... .</description>
        <language>fa</language>
        <pubDate>2026-06-16 11:22:21</pubDate>
        <image>
            <url>https://files.virgool.io/upload/publication/zrx0w0iis1vi/zqrkyl.png</url>
            <title>نشریه دایکه</title>
            <link>https://virgool.io/dayche-group-Blog</link>
        </image>

                    <item>
                <title>تحلیل بازاریابیِ خرده‌فروشی‌ها – بخش هشتم</title>
                <link>https://virgool.io/dayche-group-Blog/%D8%AA%D8%AD%D9%84%DB%8C%D9%84-%D8%A8%D8%A7%D8%B2%D8%A7%D8%B1%DB%8C%D8%A7%D8%A8%DB%8C%D9%90-%D8%AE%D8%B1%D8%AF%D9%87%D9%81%D8%B1%D9%88%D8%B4%DB%8C%D9%87%D8%A7-%D8%B4%D8%A8%DA%A9%D9%87%D9%87%D8%A7%DB%8C-%D8%B9%D8%B5%D8%A8%DB%8C-%D9%85%D8%B5%D9%86%D9%88%D8%B9%DB%8C-%D8%A8%D8%AE%D8%B4-%D9%87%D8%B4%D8%AA%D9%85-akl0qbfgz7eh</link>
                <description>باز هم به مثال مطالعه‌ی موردی خرده‌فروشی‌ دایکه در رابطه با تحلیل‌های بازاریابی و کمپین خوش آمدید. تا اینجای کار، داشتیم روی مسئله‌ی دسته‌بندی کار می‌کردیم تا مشتریانی با احتمال بالاتر خرید کالا از کاتالوگ‌های کمپین را شناسایی کنیم. در مقاله‌ی آخر مربوط به انتخاب مدل، متوجه شدیم که شبکه‌های عصبی مصنوعی، برای مسئله‌ی دسته‌بندی ما بهتر از رگرسیون لجستیک و الگوریتم‌های درخت تصمیم عمل می‌کنند. در مقاله‌ی حاضر، قصد داریم به درک شهودی و ساده‌ای از شبکه‌های عصبی مصنوعی برسیم که از مغزمان الهام می‌گیرند. در چند قسمت بعدی، راجع به آن دسته از خصوصیات مغز که شبکه‌های عصبی می‌کوشند تقلید کنند یاد می‌گیریم؛ چندتایی از این خصوصیات عبارتند از:دیدن با زبان‌!اریک ویهنمیر[1] قله‌ی اورست را در سال ۲۰۰۱ فتح کرد. با این کار، او اولین کوهنورد نابینایی شد که به این فتح شکوهند نائل شده بود. اریک پیگیری این علاقه‌مندی را ازطریق دستگاهی به‌نام برین‌پورت[2]، که به او کمک کرد با زبانش ببیند، در سنگ‌نوردی به حد اعلا رساند! این وسیله دوربینی در یک سمتش دارد که به چند صد الکترود ریز متصل است که اریک روی زبانش قرار می‌دهد تا موانع موجود در مسیرش را حس کند. این تجربه به‌واسطه‌ی یادگیری باورنکردنی سازگارپذیری مغز انسان برای اریک ممکن شد. دفعات اول، زمانی‌که اریک استفاده از این دستگاه را شروع کرد، گزیدگی روی زبانش حس می‌کرد که با تجارب دیگری همراه بود. رفته‌رفته مغز اریک یاد گرفت تا هر تجربه را به احساسات متمایز دیگر ربط دهد و این امر، توانایی دیدن را برایش امکان‌پذیر کرد. این داستانی استثنائی راجع به قابلیت سازش‌پذیری مغزمان – خصوصیتی که الهام‌بخش الگوریتم یادگیری ماشین، یعنی شبکه‌های عصبی مصنوعی است – است.حلقه‌های پس‌خورد و پیش‌خورد شبکه‌های عصبیمغز ازطریق شبکه‌ی پیچیده‌ای از رشته‌های عصبی به‌نام شبکه‌های عصبی زیستی، با سایر بخش‌های بدن در ارتباط است. مغز با مکانیسم قدرتمندی کار می‌کند که شامل حلقه‌های پس‌خورد و پیش‌خورد درون شبکه‌های عصبی پیچیده جای دارند. برای مثال، مکانیسم پیش‌خورد مستلزم ورودی‌هایی از اندام‌های حسی، مثل چشم‌ها و گوش‌ها، است که به خروجی‌ها، یعنی اطلاعات و درک تبدیل می‌شوند. از سوی دیگر، مکانیسم پس‌خورد باعث می‌شود مغز با اندام‌های حسی ارتباط برقرار کند و ورودی‌های آنها را اصلاح نماید.برای یادگیری بهتر راجع به این موضوع، اجازه دهید چند آزمایش کوچک انجام دهیم. برای آزمایش اول، چشمان خود را ببنیدید و واژگان زیر را در بازه‌های زمانی ۱۰ ثانیه‌ای، با هدف مصورسازی یا تصویرسازی آنها، بیان کنید.اژدهادهکدهقاتل اژدهابه احتمال زیاد، با اژدهایی که به دهکده‌ای حمله می‌کند و توسط قاتل اژدها کشته می‌شود، حس بسط‌یافته‌ای را مجسم می‌کنید. چیزی که همین الان درک کردید، قابلیت استثنائی مغز در استخراج اطلاعاتی راجع به این واژگان در کسری از ثانیه و تصویرسازی توالی کامل رویدادها بدون استفاده از چشمان‌تان است. این قابلیت منبع تصور بسط‌یافته‌ی است که مغز انسان پردازش می‌کند. در این مورد، یک شکل از ورودی (واژگان) ازطریق پردازش پیچیده‌ای در مغزمان، شکل دیگری از ورودی (تصویرسازی) را تولید می‌کند.آزمایش دوم در شناخت حلقه‌ی پس‌خورد و پیش‌خورد مغزمان مفید است. مواجه با جمله‌ی زیر در برخی از سایت‌های رسانه‌ی اجتماعی خیلی محتمل است. بگذریم، جمله‌ی داخل کادر متنی پایین را بخوانید.شبکه‌های عصبی مصنوعی – مثال مطالعه‌ی موردی خرده‌فروشیشبکه‌های عصبی مصنوعی به‌هیچ وجه از پیچیدگی‌های شبکه‌های عصبی زیستی برخوردار نیستند، اما نباید فراموش کنیم که شبکه‌های عصبی زیستی متحمل میلیون‌ها سال تکامل شده‌اند. از سوی دیگر، شبکه‌های عصبی مصنوعی (از اینجا به بعد، شبکه‌های عصبی) تاریخچه‌ای نزدیک به نیم‌قرن دارند. در دهه‌ی ۱۹۹۰، شبکه‌های عصبی محبوبیت‌شان را به الگوریتم‌های یادگیری ماشین مثل ماشین‌های بردار پشتیبان و غیره باختند. هرچند، تقریباً در دهه‌ی گذشته، به‌دلیل پیدایش یادگیری عمیق، علاقه‌مندی تجدیدشده‌ای به شبکه‌های عصبی شکل گرفت. بیایید سعی کنیم طراحی شبکه‌های عصبی و ویژگی‌های آنها را با استفاده از مطالعه‌ی موردی خرده‌فروشی‌مان بشناسیم.همان‌طور که در شکل می‌بینید، شبکه‌های عصبی را می‌توان به‌طور گسترده‌ای به سه لایه تقسیم کرد؛ ورودی، پنهان و خروجی. لایه‌ی پنهان نوعی ویژگی فرعی است که شبکه‌های عصبی را از سایر مدل‌های پیش‌بین مجزا می‌کند. اگر لایه‌ی پنهان را از این طرح حذف کنیم، به رگرسیونی ساده (برای برآورد) یا رگرسیون لجستیک (برای دسته‌بندی) تبدیل می‌شود. لایه‌ی ورودی این طرح صرفاً متغیرهای ورودی هستند. برخی از متغیرهای ورودی مطالعه‌ی موردی خرده‌فروشی که در مقالات قبلی بحث کردیم عبارتند از:لایه‌ی خروجی، برای مسئله‌ی دسته‌بندی در شناسایی مشتریانی که به کمپین‌ها واکنش مثبت نشان می‌دهند، متغیر دوتایی معرف واکنش‌دهندگان تاریخی (۱/۰) است.ساختار ریاضی شبکه‌های عصبیاین بخش ساختار ریاضی شبکه‌های عصبی را توصیف می‌کند. اگر این مبحث برای‌تان زیادی پیچیده است، پیشنهاد می‌کنم فعلاً از این بخش بگذرید و قسمت بعدی، یعنی کاربرد شبکه‌های عصبی را مطالعه کنید.اجازه دهید به لایه‌ی پنهان برگردیم؛ هر لایه‌ی پنهان چندین گره پنهان (دایره‌های نارنجی در شکل بالا) دارد. هر گره پنهان مجموع موزونی از ورودی مربوط به متغیرهای ورودی می‌گیرد. عبارت زیر مجموع موزون متغیرهای ورودی‌ای را ارائه می‌دهد که گره‌های پنهان به‌عنوان ورودی می‌گیرند. این متغیرهای پنهان با سیگنال‌های ورودی‌ای که اندام‌های حسی‌مان به مغزمان می‌فرستند قابل قیاسند؛ مثلاً، زمانی‌ که آتشی دوروبرتان باشد، آتش را می‌بینید، زبانه‌کشیدن آتش را می‌شنوید، دود را استشمام می‌کنید و پوست‌تان داغ می‌شود (تجربه‌ی حسی کاملی ازطریق چندین گره ورودی).برای شروع، وزن‌های  W₀ و ₍ پنهان ⇾ ورودی ₎ Wᵢᵀ  را به‌صورت تصادفی انتخاب می‌کنیم، سپس، آنها را به‌طور ترجیعی تعدیل می‌کنیم تا با ورودی‌های مطلوب (در لایه‌ی ورودی) همخوان شوند. مثال آتش بالا را ادامه می‌دهیم؛ اگر سیگنال‌های حسی مربوط به آتش خیلی قوی باشند، تمایل جانور به محافظت از خود کنترل را به‌دست می‌گیرد. هرچند، سیگنال‌های حسی مربوط به شعله‌ی اجاق آشپزی را هم باید برای انسان‌هایی که آشپزی می‌کنند لحاظ کنید. بنابراین، وزن‌ها باید برمبنای استفاده از آتش و محافظت از خود تعدیل شوند.در لایه‌ی پنهان، مجموع موزون خطی بالا [ ᵢ(گره پنهان)]، ازطریق تابعی غیرخطی به شکل غیرخطی تبدیل می‌شود. این تبدیل معمولاً‌ با استفاده از تابع فعال‌سازی سیگموئید انجام می‌شود؛ بله، این همان تابع لاجیت رگرسیون لجستیک است. عبارت زیر نشان‌دهنده‌ی این پردازش است.حواستان باشد که  0 ≤ ᵢ(پنهان)P ≥ ١ است؛ خروجی [ᵢ(پنهان)P] گره‌های پنهان مختلف (j)، متغیرهای ورودی گره خروجی پایانی می‌شود:این خروجی موزون خطی ازطریق تابع سیگموئید مجدداً‌ به شکل غیرخطی تبدیل می‌شود. عبارت زیر، احتمال تبدیل مشتری، (واکنش مشتری)P برمبنای متغیرهای ورودی‌اش است.الگوریتم‌های شبکه‌ی عصبی (مثل پس‌انتشار) وزون‌ها را مکرراً‌ برای هر دو لینک (یعنی خروجی ⇾ پنهان ⇾ ورودی ) تعدیل می‌کنند تا خطای پیش‌بینی را کاهش دهند. یادتان باشد که وزن‌های ساختار ما عبارتند از?، وزن‌های ₍ پنهان ⇾ ورودی ₎ W₀ ، Wᵢ  و ₍ پنهان ⇾ ورودی ₎ Uᵢ و U₀ .مزایا و معایب استفاده از شبکه‌های عصبیاجازه دهید برخی از مهمترین مزایا و معایب استفاده از شبکه‌های عصبی در توسعه‌ی مدل را به‌طور خلاصه مطرح کنیم.مزایا۱. شبکه‌های عصبی روش‌های بسیار تطبیق‌پذیری برای حل چهار دسته از شش دسته‌ی گسترده‌ی وظایف علم داده، یعنی دسته‌بندی، برآورد، پیش‌بینی و خوشه‌بندی (نقشه‌ی خودسازنده) ارائه می‌دهند. این شش دسته‌ی گسترده از وظایف علم داده در مقاله‌ی قبلی (دیاگرام بالا) مطرح شدند.۲. شبکه‌های عصبی به‌دلیل لایه‌ی پنهان که اطلاعات نویزدار را جذب می‌کند، (مثل مغزمان) به نویز موجود در داده‌های ورودی حساسند.۳. شبکه‌های عصبی برای پرداختن به روابط فازی/ غیرخطی بین متغیرهای ورودی و متغیر خروجی مناسب‌ترند.معایب۱. شبکه‌های عصبی اغلب به‌عنوان جعبه‌های سیاه (مثل مغزمان) تلقی می‌شوند، چرا که رابطه‌ی بین متغیرهای ورودی و خروجی را به‌وضوح برجسته نمی‌کنند. این خصیصه در درخت‌های تصمیم که راهکارهای بسیار شهودی‌ای ارائه می‌دهند خیلی نامحتمل است.۲. هنگام طراحی ساختار شبکه‌های عصبی، هیچ قانون ثابتی برای انتخاب تعداد لایه‌ها و گره‌های پنهان وجود ندارد. این امر مستلزم آن است که دانشمندان خبره‌ی داده مدل‌های شبکه‌های عصبی را توسعه دهند.۳. شبکه‌های عصبی اغلب مستعد بیش‌برازش هستند، بنابراین، تحلیل‌گران باید نتایج را به‌دقت بررسی کنند.مخلص کلامشبکه‌های عصبی مصنوعی روزهای اولیه‌شان را سپری می‌کنند، اما مطمئناً کلی امیدبخش خواهند بود. طبیعت مغز ما را با بردباری و به‌دقت طراحی و تعدیل کرده است تا شبکه‌های عصبی زیستی استثنائی‌ا‌ی خلق شوند. شک دارم انسان‌ها هم به اندازه‌ی طبیعت باحوصله باشند. این زیبایی‌ای است که همگی باید از طبیعت فراگیریم.در بخش بعدی مطالعه‌ی موردی دایکه می‌بینیمتان!‌</description>
                <category>نشریه دایکه</category>
                <author>dayche-group</author>
                <pubDate>Tue, 22 Oct 2019 16:34:01 +0330</pubDate>
            </item>
                    <item>
                <title>تحلیل بازاریابیِ خرده‌فروشی‌ها – بخش هفتم</title>
                <link>https://virgool.io/dayche-group-Blog/%D8%AA%D8%AD%D9%84%DB%8C%D9%84-%D8%A8%D8%A7%D8%B2%D8%A7%D8%B1%DB%8C%D8%A7%D8%A8%DB%8C%D9%90-%D8%AE%D8%B1%D8%AF%D9%87%D9%81%D8%B1%D9%88%D8%B4%DB%8C%D9%87%D8%A7-%D8%A8%D8%AE%D8%B4-%D9%87%D9%81%D8%AA%D9%85-frj3smogwvpo</link>
                <description>انتخاب مدلاین بخش از سری مقالات تحلیل بازاریابیِ خرده‌فروشی‌ دایکه ، ادامه‌ی مثال مطالعه‌ی موردی خرده‌فروشی تحلیل‌های بازاریابی و کمپین است. در دو بخش قبلی، دو الگوریتم درخت تصمیم (CART و C4.5) برای دسته‌بندی را مطرح کردیم. مثال مطالعه‌ی موردی قبلیِ راجع به بانکداری و مدیریت خطر را به یاد آورید که در آن رگرسیون لجستیک، رویکرد دیگری برای حل مسائل دسته‌بندی را بحث کردیم. به‌علاوه، چندین الگوریتم یادگیری ماشین و آماری دیگری هم هست که برای کارهای دسته‌بندی، مثل موارد ذکرشده در زیر، همان‌اندازه پرقدرتند:ماشین‌های بردار پشتیبان[1]جنگل تصادفی[2]شبکه‌های عصبی مصنوعیتحلیل تشخیصیمدل تجمیعی boostingدسته‌بندی بیز ساده[3]این لیست کامل نیست، اما شامل برخی از رویکردهای رایج است. کلیه‌ی این رویکردها را در مقالات بعدی دایکه مطرح می‌کنیم. حالا سؤال این است: چرا تعداد زیادی رویکرد مختلف برای حل مسئله‌ای مشابه وجود دارد؟ سؤال مهمتری که هرکسی می‌پرسد این است: کدامیک از این رویکردها بهترین است؟ پاسخ سؤال دوم هیچکدام است! بله، بهترین رویکرد به نوع داده‌هایی که با آنها کار می‌کنید بستگی دارد و از آنجایی‌که داده‌ها در هر شکل و اندازه‌ای موجودند، پس نمی‌توانید یک بهترین رویکرد برای همه‌ی مسائل داشته باشید. بنابراین، توسعه‌ی مدل‌هایی با رویکردهای مختلف و انتخاب بهترین مدل برای داده‌های شما تمرین مهمی در علم داده و تحلیل است. در این مقاله، در مورد عوامل تأثیرگذار روی فرایند انتخاب مدل بحث می‌کنیم. هرچند، پیش از شروع بحث اجازه دهید سریعاً برخی از کارهایی که دانشمندان داده انجام می‌دهند را بررسی کنیم؛ زمانی‌که وارد بخش‌های بعدی این مثال مطالعه‌ی موردی خواهیم شد، این موضوع به دردمان می‌خورد.وظایف علم دادهاساساً وظایفی که دانشمندان داده انجام می‌دهند را می‌توان به شش دسته‌ی گسترده‌ (همان‌طور که در زیر ارائه شده است) گروه‌بندی کرد. لطفاً توجه کنید که حتی وظایف علم داده‌ی مدرن، مثل تحلیل‌های وب و رسانه‌های اجتماعی، متن‌کاوی، تحلیل‌های تصویری و شناسایی الگوی صوت از این شش دسته‌ی گسترده استفاده کرده‌اند.وظایف علم داده‌همان‌طور که متوجه شدید، در این مطالعه‌ی موردی، تا اینجا ۳ وظیفه از لیست بالا، یعنی «توصیف» (تحلیل کاوشگرانه‌ی داده‌ها)، «وابستگی» (تحلیل وابستگی) و «دسته‌بندی» (درخت‌های تصمیم؛ CART و C4.5) را انجام دادیم. EDA تمرین بسیار مهمی‌ست که مدل‌های پیشگویانه‌ای در جهت درست استخراج می‌کند.در بخش‌های پایانی این مطالعه‌ی موردی، چندین «برآورد» انجام می‌دهیم (یعنی تحلیل رگرسیون برای برآورد درآمد تولیدشده توسط مشتریان ازطریق کمپین‌ها). اجازه دهید برای رسیدگی مسئله‌ی طبقه‌بندی‌مان به انتخاب مدل برگردیم.انتخاب مدل – مثال مطالعه‌ی موردی خرده‌فروشیبه مثال مطالعه‌ی موردی خرده‌فروشی‌مان برمی‌گردیم؛ در این مثال، شما مدیر ارشد تحلیل و رئیس راهبرد کسب‌وکار فروشگاه آنلاینی به‌نام درس‌اسمارت هستید که در عرضه‌ی پوشاک تخصص دارد. ازطریق تحلیل کاوشگرانه‌ی دقیق داده‌ها، چندین عامل که نقش حیاتی‌ای در واکنش مشتریان به کمپین بازاریابی ایفا می‌کنند را پیدا می‌کنید؛ برخی از این فاکتورها عبارتند از:تازگی: # بازدیدها و خریدهای اخیر از وب‌سایت شرکتتوالی خریدها: تأخیر زمانی بین خریدها در ۶ ماه گذشتهروش پرداخت به‌کاررفته: پرداخت نقدی هنگام تحویل، پرداخت با کارت اعتباری، بانکداری اینترنتی و غیرهداده‌های بازاریابی گردآوری شده: گروه‌بندی برمبنای سبک زندگی (یعنی، دوستداران کالاهای لوکس، سالخوردگان طرفدار کالاهای بسیار گران‌قیمت و مزدبگیران دائمی).روند مخارج سال گذشته: مقدار پول خرج‌شده در سال گذشتهالگوی کاربرد کوپن توسط مشتریشما مدل‌های چندمتغیره‌ی فوق (یعنی رگرسیون لجستیک، SVM، درخت‌های تصمیم و غیره) را برای مدل‌سازی رفتار مشتریان و تولید امتیازات تمایل به خرید امتحان کرده‌اید. انتخاب مدل درست به دو عامل زیر بستگی دارد:۱. قدرت پیشگویانه‌ی مدل‌ها۲. یکپارچگی عملیات‌ها و کسب‌وکار۱. قدرت پیشگویانه‌ی مدل‌هاعامل اول در انتخاب مدل، قدرت پیشگویانه‌ی کلی مدل موردنظر در مقایسه با سایر مدل‌ها است. برای این مسئله‌ی دسته‌بندی، ناحیه‌ی زیر منحنی عملیاتی گیرنده ([4] AUROC) احتمالاً بهترین روش برای ارزیابی قدرت پیشگویانه‌ی مدل‌ها است (راجع به AUROC بیشتر بخوانید). گاهی اوقات از ضریب جینی[5] برای ارزیابی قدرت پیشگویانه‌ی مدل‌ها استفاده می‌شود؛ جینی نوع دیگری از AUROC است و از لحاظ ریاضی به‌صورت زیر بیان می‌شود:در نمودار زیر، AUROC برای شبکه‌های عصبی مصنوعی، رگرسیون لجستیک و درخت تصمیم CART نمایش داده شده است. توجه داشته باشید که در اینجا قدرت پیشگویانه‌ی منحنی مدل کامل (به رنگ سبز)، ۱۰۰ درصد است و مدل تصادفی (به رنگ قرمز) پیشگویی را ازطریق پرتاب سکه نمایش می‌دهد. مقادیر AUROC نمونه‌ی آزمایشی این سه مدل عبارتند از:ناحیه‌ی زیر ROC برای مدل‌های مختلفدر اینجا، درخت تصمیم خیلی پایین‌تر از مدل‌های دیگر اجرا می‌شود. این موضوع اغلب در درخت‌های تصمیم دیده می‌شود، اما هنوز هم به‌دلیل راهکارهای ساده و بسیار فهم‌پذیر خیلی محبوب و سودمندند. شبکه‌های عصبی مصنوعی در این مورد، با ناحیه‌ی کمی بالاتر زیر ROC، یک درجه بالاتر از رگرسیون لجستیک اجرا می‌شوند. بنابراین، براساس معیار اول، شبکه‌های عصبی مصنوعی بهترین مدل را از بین این سه مدل ارائه می‌دهند.۲. یکپارچگی عملیات‌ها و کسب‌وکاراین جنبه از انتخاب مدل هم به اندازه‌ی عامل بالا، اگر نه بیشتر، مهم است. انتخاب مدل باید برمبنای زایایی[6] مدل برای کاربرد تجاری در بلندمدت صورت گیرد. به‌خاطرسپردن عوامل زیر در شروع فرایند مدل‌سازی مفید است:۱) دسترس‌پذیری مستمر داده‌ها برای کلیه‌ی متغیرهای پیش‌بین: بسیاری اوقات، مدل‌ها برمبنای متغیرهای پیش‌بینی توسعه می‌یابند که دستیابی منظم و مستمر به آنها دشوار است. نگه‌داشتن چنین متغیرهایی در مدل، حتی اگر روی قدرت پیشگویانه‌ی بالا نیز تأثیرگذار باشند، توصیه نمی‌شود. این موضوع مخصوصاً راجع به داده‌های شخص ثالث که هر از گاهی خریداری می‌شوند واقعیت دارد.۲) مدل باید به اندازه‌ی کافی برای کالیبره‌کردن ساده باشد: هدف هر مدلی یکپارچه‌شدن خوب با سیستم‌های IT به‌کاررفته توسط کاربران کسب‌وکار است. تحلیل‌گران باید زایایی مدل برای یکپارچه‌سازی فرایند کسب‌وکار در شروع پروژه را لحاظ کنند تا از دوباره‌کاری غیرضروری در تکمیل پروژه بپرهیزند.۳) تعهد کابران کسب‌وکار به کاربرد منظم مدل‌ها: علم داده صرفاً نوعی تمرین فکری نیست. مهمترین جنبه‌ی موفقیت علم داده، تولید ارزش کسب‌وکار ازطریق بینش‌های شدنی و تعهد کاربران کسب‌وکار به عمل‌کردن به این بینش‌هاست. این تعهد کاربران کسب‌وکار، از مشارکت و درکشان از فرایند ساخت مدل نشأت می‌گیرد. دانشمندان علم داده باید رابطه‌ی خوبی با کابران کسب‌وکار برقرارکنند تا اعتمادشان را جلب نمایند.مخلص کلامدر این مقاله، متوجه شدیم که شبکه‌های عصبی مصنوعی، برای مجموعه‌داده‌ی ما کمی بهتر از رگرسیون لجستیک و الگوریتم‌های درخت تصمیم عمل می‌کنند. پیش از پرداختن به ادامه‌ی بخش بعدی این مطالعه‌ی موردیِ دایکه، یعنی برآوردها ازطریق رگرسیون، شبکه‌های عصبی مصنوعی را در مقاله‌ی بعدی مطرح می‌کنیم. تا بعد![1]  Support Vector Machines[2]  Random Forest[3]  Naïve Bayes Classifiers[4]  area under receiver operating curve[5]  Gini coefficient[6]  productionization</description>
                <category>نشریه دایکه</category>
                <author>dayche-group</author>
                <pubDate>Sun, 13 Oct 2019 16:14:26 +0330</pubDate>
            </item>
                    <item>
                <title>تحلیل بازاریابیِ خرده‌فروشی‌ها – بخش ششم</title>
                <link>https://virgool.io/dayche-group-Blog/%D8%AA%D8%AD%D9%84%DB%8C%D9%84-%D8%A8%D8%A7%D8%B2%D8%A7%D8%B1%DB%8C%D8%A7%D8%A8%DB%8C%D9%90-%D8%AE%D8%B1%D8%AF%D9%87%D9%81%D8%B1%D9%88%D8%B4%DB%8C%D9%87%D8%A7-%D8%A8%D8%AE%D8%B4-%D8%B4%D8%B4%D9%85-ai8ntex4r8pa</link>
                <description>مقاله‌ی حاضر دایکه، ادامه‌ی مثال مطالعه‌ی موردی خرده‌فروشی است که چند هفته‌ی گذشته روی آن کار می‌کردیم. بخش‌های قبلی مثال مطالعه‌ی موردی را می‌توانید در لینک‌های زیر پیدا کنید:بخش ۱: مقدمهبخش ۲: تعریف مسئلهبخش ۳: EDAبخش ۴: تحلیل وابستگیبخش ۵: درخت تصمیم (CART)اگر از مقاله‌ی قبلی یادتان باشد، الگوریتم CART درخت‌های تصمیمی تولید می‌کند که فقط گره‌های فرزند دوتایی دارند. در مقاله‌ی حاضر، الگوریتم دیگری یاد می‌گیریم تا درخت‌های تصمیمی با گره‌های فرزند چندتایی بسازیم. چندین روش برای دستیابی به این هدف موجود است، مثل CHAID (شناساگر تعامل خودکار مربع خی[1]). در اینجا، راجع به الگوریتم c4.5 می‌آموزیم تا درخت‌های تصمیمی با گره‌های فرزند چندتایی تولید کنیم. چرا که این الگوریتم از مفهومی استفاده می‌کند که به دلم نشسته است.آنتروپیقانون اول ترمودینامیک مربوط به تبدیل انرژی را در دبیرستان آموختیم. طبق این قانون:انرژی نه تولید می‌شود، نه از بین می‌رود؛ به بیان دیگر، انرژی کل جهان ثابت است.اولین واکنش بیشتر دانش‌آموزان پس از فراگیری این واقعیت این بود: پس چرا برای ذخیره‌ی الکتریسیته و سوخت خودمان را به زحمت بیندازیم؟ اگر انرژی کل جهان ثابت و محفوظ است، پس میزان نامحدودی از انرژی برای مصرف داریم که هیچ‌گاه از بین نمی‌رود.هرچند، قانون دوم ترمودینامیک این راحتی خیال مربوط به تلف‌شدن انرژی را نابود می‌کند. آنتروپی منشأ اصلی قانون دوم ترمودینامیک است. آنتروپی میزان بی‌نظمی یا تصادفی‌بودن در جهان است. جهت کلی جهان از نظم به سوی بی‌نظمی یا تصادفی‌بودن بالاتر است. قانون دوم می‌گوید:آنتروپی کل یا بی‌نظمی/ تصادفی‌بودن کل جهان همواره درحال افزایش است.بسیار خُب، اجازه دهید مثالی بزنیم تا این قانون را بهتر بفهمیم. زمانی‌که برای راه‌انداختن خودروتان از سوخت استفاده می‌کنید، بنزین کاملاً منظم (انرژی فشرده) به اشکال بی‌نظمی از انرژی، مثل گرما، صوت، جنبش و غیره تبدیل می‌شود. حین این فرایند، کار تولید می‌شود تا موتور خودرو را به‌راه اندازد. هر چه این انرژی تصادفی‌تر یا بی‌نظم‌تر باشد، استخراج کاری هدف‌دار از آن دشوارتر/ ناممکن‌تر می‌شود. پس به نظرم ما به کار اهمیت می‌دهیم، نه به انرژی. به بیان دیگر، هر چه آنتروپی یا تصادفی‌بودن سیستمی بالاتر باشد، تبدیل آن به کار معنادار دشوارتر می‌شود. فیزیکدانان آنتروپی سیستم را توسط فرمول زیر تعیین می‌کنند:آنتروپی، اصل نظریه‌ی اطلاعات هم هست. کلاده شانون[2]، پدر نظریه‌ی اطلاعات، نبوغش را به‌کار گرفت تا روابط بین ترمودینامیک و اطلاعات را شناسایی کند. وی طی پیام خاصی، تعریف آنتروپی زیر را برای سنجش تصادفی‌بودن پیشنهاد کرد:برای مثال، آنتروپی (تصادفی‌بودن) سکه‌ی سالم، با شانس یکسان شیر و خط، ۱ بیت (طبق محاسبه‌ی زیر) است. توجه داشته باشید که واحد آنتروپی در نظریه‌ی اطلاعات بیت است که توسط کلاده شانون ابداع شد. از همین واحد به‌عنوان واحد اصلی حافظه‌ی رایانه‌ هم استفاده می‌شود.برای ساختن درخت تصمیم و پوشیده‌خوانی اطلاعات درون داده‌ها از همین فرمول استفاده خواهیم کرد.مثال مطالعه‌ی موردی خرده‌فروشی – درخت تصمیم (آنتروپی: الگوریتم C4.5)به مثال مطالعه‌ی موردی خرده‌فروشی‌مان برمی‌گردیم؛ در این مثال، شما مدیر ارشد تحلیل و رئیس راهبرد کسب‌وکار فروشگاه آنلاینی به‌نام درس‌اسمارت هستید که در عرضه‌ی پوشاک تخصص دارد. در این مورد، هدفتان بهبود عملکرد کمپین آتی است. برای دستیابی به این هدف، داده‌های برگرفته از کمپین قبلی که کاتالوگ‌های کالاها را مستقیماً به صدها هزار مشتری از پایگاه مشتریان چند میلیون نفری ارسال می‌شد را تحلیل می‌کنید. نرخ واکنش کلی این کمپین ۴.۲ درصد بود.شما کل صدها هزار مشتری متقاضی را برمبنای فعالیت‌های ۳ ماه اخیرشان، پیش از شروع کمپین، به سه دسته تقسیم کرده‌اید. جدول زیر همان جدولی است که در مقاله‌ی قبلی، به‌منظور خلق درخت تصمیم با استفاده از الگوریتم CART به‌کار بردیم.شکل زیر، درختی با گره دوتایی است که در مقاله‌ی قبلی، با استفاده از CART ساختیم.درخت تصمیم – CARTبیایید ببینیم می‌توانیم با استفاده از آنتروپی یا الگوریتم c4.5 درخت بهتری بسازیم یا نه. از آنجایی‌که الگوریتم c4.5 قادر به تولید درخت‌های تصمیمی با گره‌های چندتایی است، پس یک احتمال دیگری از درخت (با سه گره – پایین؛ متوسط؛ بالا) خواهیم داشت. این علاوه بر درخت‌هایی دوتایی است که در مقاله‌ی قبلی کاوش کردیم.روش کار c4.5، مقایسه‌ی آنتروپی کلیه‌ی درخت‌های ممکن با داده‌های اصلی (داده‌های خط‌مبنا) است. سپس، درختی با بیشترین حصول (بازده) اطلاعاتی، یعنی اختلاف آنتروپی‌ها را انتخاب می‌کند:بنابراین، اول باید آنتروپی خط‌مبنای داده‌هایی با ۴.۲ درصد تبدیل[3] (۴۲۰۰ مشتری تبدیل‌شده از بین ۱۰۰،۰۰۰ مشتری متقاضی) را محاسبه کنیم. توجه کنید که ۹۵.۸ درصد (۴.۲٪ - ۱۰۰٪ =) در جمله‌ی دوم، درصد مشتریان تبدیل‌نشده است.این همان مقداری است که در پایین‌ترین ردیف جدول زیر برای آنتروپی کل به‌دست آوردیم.حالا بیایید با محاسبه‌ی آنتروپی‌های اجزاء تکی درخت اول (با سه گره – پایین؛ متوسط؛ بالا)، آنتروپی درخت را بیابیم.حالا آنتروپی کل این درخت، همان مجموع موزون کلیه‌ی اجزاءاش است. در اینجا، وزن‌ها، تعداد مشتریان یک گره تقسیم بر تعداد کل مشتریان هستند؛ مثلاً، ۰.۴ = ۴۰،۰۰۰/۱۰۰،۰۰۰  برای گره اول .نهایتاً، باید مقدار حصول اطلاعات را محاسبه کنیم، یعنی:ضمناً، حصول اطلاعات درختی با سه گره، در مقایسه با سایر درخت‌ها از همه بالاتر است (به جدول بالا نگاهی بیندازید). بنابراین، الگوریتم c4.5 با استفاده از آنتروپی، درخت تصمیم زیر را خلق می‌کند:درخت تصمیم c4.5 با استفاده از آنتروپیو اما حرف آخرچقدر آنتروپی جالب است! بله، اعتراف می‌کنم عاشق فیزیکم. هرچند، این رابطه‌ی بین ترمودینامیک و اطلاعات هنوز هم موهای تنم را سیخ می‌کند. ایده‌ی کلی این است که اطلاعات عدم قطعیت یا تصادفی‌بودن سیستم را حذف می‌کند. پس، با استفاده از اطلاعات می‌توان مسیر را از بی‌نظمی به نظم تغییر داد! بله، سرنوشت جهان این‌طور رقم خورده است که به سوی بی‌نظمی یا تصادفی‌بودن پیش برود، اما هنوز می‌توانیم از اطلاعات برای ایجاد نظم در سیستم‌های کوچک استفاده کنیم.تا مقاله‌ی بعدی![1] CHi-squared Automatic Interaction Detector[2] Claude Shannon[3] conversion</description>
                <category>نشریه دایکه</category>
                <author>dayche-group</author>
                <pubDate>Sat, 12 Oct 2019 17:53:10 +0330</pubDate>
            </item>
                    <item>
                <title>تحلیل بازاریابیِ خرده‌فروشی‌ها – بخش پنجم</title>
                <link>https://virgool.io/dayche-group-Blog/%D8%AA%D8%AD%D9%84%DB%8C%D9%84-%D8%A8%D8%A7%D8%B2%D8%A7%D8%B1%DB%8C%D8%A7%D8%A8%DB%8C%D9%90-%D8%AE%D8%B1%D8%AF%D9%87%D9%81%D8%B1%D9%88%D8%B4%DB%8C%D9%87%D8%A7-%D8%A8%D8%AE%D8%B4-%D9%BE%D9%86%D8%AC%D9%85-x3hhnhmm4gns</link>
                <description>مقاله‌ی حاضر دایکه  ادامه‌ی همان مثال مطالعه‌ی موردی‌ است که طی چند هفته‌ی گذشته کار می‌کردیم. چهار بخش قبلی را می‌توانید در لینک‌های زیر بیابید:بخش ۱: مقدمهبخش ۲: تعریف مسئلهبخش ۳: EDAبخش ۴: تحلیل وابستگیدر این مقاله، راجع به نوعی درخت تصمیم به‌نام درخت رگرسیون و دسته‌بندی ([CART[1) به‌منظور توسعه‌ی مدل سریع و نخراشیده‌ای برای همان مثال مطالعه‌ی موردی قبلی بحث می‌کنیم. اما پیش از شروع بحث، اجازه دهید اصول موارد زیر را بررسی کنیم:درخت تصمیمبیاید بپذیریم که همه‌ی ما پیش از برداشتن تکه‌ای پیتزا از داخل جعبه، سریعاً اندازه‌ی تکه و نسبت‌‌های مواد روی آن را تحلیل می‌کنیم. در این بهینه‌سازی، عمدتاً در جستجوی بزرگترین تکه‌ی حاوی بیشترین مواد موردعلاقه‌تان هستید (و احتمالاً‌ از تکه‌هایی که حاوی موادی هستند که اصلاً دوست ندارید پرهیز می‌کنید). با این اوصاف، ترجیحاً‌ این پسربچه (در شکل) را حریص نمی‌نامیم. او صرفاً می‌کوشد کیک تولدش را طوری ببرد که تکه‌ی مدنظرش حاوی بیشترین مقدار از طعم موردعلاقه‌اش باشد. گوشه‌ی بالایی کیک پسند ذائقه‌ی اوست؛ حاوی گیلاس‌های قرمز محبوبش و مقدار نه چندان زیادی از سیب سبز. او باید فقط با دو ضربه چاقو برش تمیزی ایجاد کند، وگرنه مهمانان جشن‌اش  از کاربرد ناشیانه‌ی او از چاقو لذت نخواهند برد. این پسربچه می‌تواند با به‌کارگیری مهارتی بی‌نقص و استفاده از درخت تصمیم در مغزش، تکه‌ی کاملی ببرد تا از طعم آن لذت وافی را ببرد. اجازه دهید به هنرورزی این پسربچه نگاهی بیندازیم:کیک درخت تصمیم – الگوریتم CARTاو برش کیک را با نسبت‌هایی از تکه‌های قرمز و سبز (۵۰٪ - ۵۰٪) آغاز کرد. یادتان باشد که او بیشترین تعداد از تکه‌های قرمز و کمترین تعداد از تکه‌های سبز را روی برشش می‌خواست. برش او، یعنی یک‌چهارم کیک، ۷۱ درصد تکه‌ی قرمز و ۲۹ درصد تکه‌ی سبز دارد. بد هم نیست! الگوریتم درخت تصمیم دقیقاً‌ این‌طوری کار می‌کند. درست مثل مسئله‌ی بالا، الگوریتم CART می‌کوشد گره ریشه (کل کیک) را فقط به دو تکه (نه بیشتر) برش دهد/ تقسیم کند. هرچند، الگوریتم‌های درخت تصمیم دیگری هم هستند که در مقاله‌ی بعدی مطرح می‌کنیم؛ این الگوریتم‌ها قادرند گره ریشه را به قطعات زیادی تقسیم کنند.باید خاطرنشان کنم که گرچه در این مقاله، از داده‌های مجزا (مثل گیلاس‌های قرمز و سیب‌های سبز) برای درخت تصمیم استفاده می‌کنیم، اما CART قادر است داده‌های کمی مثل سن، فاصله و غیره را هم به‌طور مساوی تقسیم کند. بیایید الگوریتم درخت تصمیم CART را بیشتر بررسی کنیم.درخت رگرسیون و دسته‌بندی (CART)از نظر من، الگوریتم‌هایی مثل الگوریتم پیج‌ رنک گوگل[2]، الگوریتم‌های رمزنگاری اَلن تورینگ یا چندتایی از الگوریتم‌هایی یادگیری ماشین خیلی شگفت‌انگیزند. برای من، الگوریتم‌ها بازتابی از اندیشه‌ی ساختاریافته‌ی ابرازشده ازطریق منطق هستند. برای مثال، الگوریتم CART توسیعی از فرایندی‌ست که داخل مغز این پسربچه، ضمن تقسیم‌کردن کیک تولدش رخ می‌دهد. او سعی داشت بزرگترین تکه‌ی حاوی بیشترین گیلاس و کمترین سیب را برای خودش ببرد. در این مسئله، او دو هدف داشت.۱. جداسازی بزرگترین تکه با برشی تمیز۲. بیشینه‌سازی تعداد گیلاس‌های روی این تکه، ضمن کمینه‌سازی تعداد سیب‌های سبزالگوریتم درخت تصمیم CART تلاشی برای دستیابی به دو هدف فوق است. معادله‌ی زیر نمایشی از ترکیب این دو هدف است. از این معادله نترسید، این معادله درواقع خیلی ساده است؛ پس از حل مثالی در قسمت بعدی، متوجه سادگی این معادله خواهید شد.• اولین جمله‌ی معادله‌ی فوق، یعنی 2Pₗ Pᵣ هدف اول را کنترل می‌کند تا بزرگترین تکه بریده شود. اجازه دهید این جمله را «(تکه‌ی بزرگ)Ψ» بنامم، چرا که مرا یاد هدف ماورای این معادله‌ی ریاضی می‌اندازد.• این در حالی‌ست که جمله‌ی دوم، یعنی ₖ₌₀ | P(K | L) - P(K | R |)∑ هدف دوم را کنترل می‌کند. این جمله را «(انتخاب گیلاس‌ها)Ψ» می‌نامم.برای مثال، ۱، ۰ = k است؛ در معادله‌ی فوق، سیب‌های سبز = ۰ و گیلاس‌های قرمز = ۱ هستند. یادتان باشد که برای مطالعه‌ی موردی ما با کمپین‌های بازاریابی، ۰، ۱ = k، مشتریان با واکنش مثبت ([r[3) و بدون واکنش مثبت ([nr[4) می‌شود. همین‌طور، برای مقالات امتیازبندی اعتبار و مطالعه‌ی موردی بانکداری (در آینده به بخش مقالات دایکه اضافه می شود)، ۰، ۱ = k، نکول‌کننده و نکول‌نکننده[5] می‌شود. هرچند، فلسفه‌ی درخت تصمیم و CART برای همه‌ی این مثال‌ها و مسائل دسته‌بندی عَملی‌تر همچنان یکی است.اجازه دهید پیش از تشریح اجزاء معادله‌ی نیکویی تقسیم فوق، برخی از مهمترین اصطلاحات فنی الگوریتم درخت تصمیم CART را تعریف کنم.اصطلاحات فنی درخت تصمیم CARTتعاریف اجزاء معادله‌ی نیکویی تقسیم در زیر ارائه شده‌اند:L: گره فرزند چپِ گره ریشهR: گره فرزند راستِ گره ریشهمطالعه‌ی موردی خرده‌فروشی – درخت تصمیم (CART)به مثال مطالعه‌ی موردی خرده‌فروشی برمی‌گردیم؛ در این مثال، شما مدیر ارشد تحلیل و رئیس راهبرد کسب‌وکار فروشگاه آنلاینی به‌نام شرکت درس‌اسمارت هستید که در حیطه‌ی پوشاک تخصص دارد. در این مثال موردی، قصد دارید عملکرد کمپین‌های آتی را بهبود بخشید. برای دستیابی به این هدف، داده‌های برگرفته از کمپین قبلی، که کاتالوگ‌های کالاها را مستقیماً به صدها هزار مشتری از پایگاه مشتریان کاملِ چند میلیون نفری ارسال کرد، را تحلیل می‌کنید. نرخ دریافت واکنش مثبت کل برای این کمپین، ۴.۲ درصد بود.شما کل صدها هزار مشتری متقاضی را برمبنای فعالیت ۳ ماه قبلی‌شان پیش از شروع کمپین، به سه دسته تقسیم کردید. جدول زیر، توزیع مشابهی را ارائه می‌کند. در این جدول، نرخ موفقیت، درصد مشتریانِ با واکنش مثبت (r) به کمپین از بین کل مشتریان متقاضی است.همان‌طور که می‌دانید، الگوریتم درخت تصمیم CART گره ریشه را فقط به دو گره فرزند تقسیم می‌‌کند. بنابراین، برای این داده‌ها، CART می‌تواند سه ترکیب از درخت‌های دوتایی بسازد (جدول زیر). باید بفهمیم بهترین تقسیم بین این سه ترکیب کدام است. نتایج در جدول زیر ارائه شده‌اند.اجازه دهید در محاسبه‌ی هر یک از ستون‌های درخت بالا کمک‌تان کنم. برای انجام محاسبات زیر، از اولین ردیف (یعنی گره چپ: گره پایین و بالا: متوسط + بالا) استفاده می‌کنیم و پس از آن، می‌توانید مابقی محاسبات را خودتان انجام دهید. برای شروع، Pₗ و Pᵣ  را به‌روش زیر محاسبه می‌کنیم:حالا محاسبه‌ی (تکه‌ی بزرگ)Ψ به سادگی زیر می‌شود:حالا به بخش بعدی معادله، یعنی (انتخاب گیلاس‌ها)Ψ می‌پردازیم. حواستان باشد که r معرف مشتریان با واکنش مثبت و nr معرف مشتریان بدون واکنش مثبت به مثال کمپین‌مان است.ممکن است بخواهید دو جمله‌ی دیگر یعنی r:P(K|R) و  nr:P(K|R)   را هم پیش از جایگزاری آنها در معادله‌ی زیر، برای دستیابی به مقدار (انتخاب گیلاس‌ها)Ψ محاسبه کنید.با این حساب، محاسبه‌ی پایانی ستون آخر، یعنی نیکویی تقسیم می‌ماند که به‌صورت زیر انجام می‌شود:‌کار نهایی، یافتن بیشترین مقدار نیکویی تقسیم در ستون انتهایی است. این محاسبه، درخت تصمیم زیر را ازطریق الگوریتم CART، با پایین روی گره چپ و متوسط + بالا روی گره راست، تولید می‌کند.درخت تصمیم – نتیجه‌ی نهایی الگوریتم CARTاین بینش کسب‌وکار مهمی است؛ به‌علاوه این‌که افراد با فعالیت بالاتر، واکنش بهتری به کمپین‌ها نشان می‌دهند. موافقم که این امر از جدول اول در بالا نیز واضح بود، اما ما علم خلق درخت تصمیم با استفاده از الگوریتم CART در فرایند را یاد گرفته‌ایم. زمانی‌که با مجموعه‌داده‌ی بزرگی سروکار دارید و می‌خواهید درخت تصمیمی ازطریق جزءبندی بازگشتی بسازید، این مهارت خیلی مفید خواهد بود.و اما حرف آخربسیار خُب، دفعه‌ی بعدی که آن تکه پیتزا را انتخاب می‌کنید، درخت تصمیم تکاملی را به یاد آورید که در بیشینه‌سازی شانس انتخاب بهترین تکه به شما کمک می‌کند. هر از گاهی، شاید بخواهید آن بهترین تکه را برای کَس دیگری کنار بگذارید – شرط می‌بندم به همان اندازه حس خوشایندی خواهید داشت!‌در مقاله‌ی بعدی دایکه، این مفهوم درخت تصمیم دارایِ گره فرزند دوتایی ازطریق الگوریتم CART را با استفاده از سایر الگوریتم‌ها، به درخت تصمیمی با بیش از دو گره بسط می‌دهیم. تا بعد![1] classification and regression tree[2] Google’s PageRank algorithm[3] responded[4] not-responded[5] loan defaulters &amp; non-defaulters</description>
                <category>نشریه دایکه</category>
                <author>dayche-group</author>
                <pubDate>Sat, 12 Oct 2019 17:21:34 +0330</pubDate>
            </item>
                    <item>
                <title>تحلیل بازاریابیِ خرده‌فروشی‌ها – بخش چهارم</title>
                <link>https://virgool.io/dayche-group-Blog/%D8%AA%D8%AD%D9%84%DB%8C%D9%84-%D8%A8%D8%A7%D8%B2%D8%A7%D8%B1%DB%8C%D8%A7%D8%A8%DB%8C%D9%90-%D8%AE%D8%B1%D8%AF%D9%87%D9%81%D8%B1%D9%88%D8%B4%DB%8C%D9%87%D8%A7-%D8%A8%D8%AE%D8%B4-%DA%86%D9%87%D8%A7%D8%B1%D9%85-dp9osdc5mbtu</link>
                <description>این بخش ادامه‌ی مثال مطالعه‌ی موردی تحلیل‌های بازاریابی است که در چند مقاله‌ی قبلی مطرح کردیم. بخش‌های قبلی  سری مقالات تحلیل بازاریابیِ خرده‌فروشی‌ دایکه  (بخش‌ ۱ ، بخش۲ و بخش۳) را می‌توانید در لینک‌های زیر بیابید. در بخش ۳، تحلیل کاوشگرانه‌ی داده‌ها (EDA) را مطرح کردیم. در مقاله‌ی حاضر، راجع به تحلیل وابستگی، که روش مفیدی برای استخراج الگوهای جالب در داده‌های مبادلاتی مشتریان است صحبت خواهیم کرد. از تحلیل وابستگی می‌توان به‌عنوان ابزار مفیدی برای تحلیل تعمیم‌ یافته‌ی کاوشگرانه‌ی داده‌ها استفاده کرد. ضمناً، تحلیل وابستگی، هسته‌ی تحلیل سبد بازار[1] یا تحلیل دنباله‌ای[2] است. بعداً در همین مقاله، از تحلیل وابستگی در مثال مطالعه‌ی موردی‌مان استفاده می‌کنیم تا کاتالوگ‌های پیشنهادی کارامدی برای کمپین‌ها و همچنین طراحی فروشگاه آنلاین (وب‌سایت) طراحی کنیم.دست‌قیچی‌ها[3]۹ یا ۱۰ سالم بود که اولین کلاس درس کاردستی در مدرسه‌مان برگزار شد. کلاس‌های درسی کاردستی در هند SUPW نامیده می‌شوند که مخفف «کار اجتماعی مفید و ثمربخش[4]» است. در جلسه‌ی اول کلاس، به هر دانش‌آموز یک برگه‌ی رنگی A4 و یک جفت قیچی داده می‌شد. در جلسه‌ی اول، کودکان پرشوروهیجانِ بی‌هدف دریافتند که قادرند برگه کاغذی را به‌روش‌های تقریباً نامحدودی ببُرند. این کار از لحاظ اجتماعی نه سودمند بود، نه ثمربخش و به تولید مقدار زیادی کاغذ باطله منجر شد. عبارت  SUPW در این مورد، «مقداری کاغذ مفید هدررفته[5]» است. بعدها، به‌واسطه‌ی تلاش‌های هدفمندتر دریافتیم که اگر از قیچی هوشمندانه استفاده شود، شکل‌های جالب زیادی از یک برگه کاغذ درمی‌آید.این دقیقاً‌ همان تجربه‌ای است که بسیاری از تحلیل‌گران هنگام مواجه با داده‌های مبادلاتی مشتریان کسب می‌کنند. منبع غنی‌ای از اطلاعات راجع به رفتار مشتری در این داده‌ها نهفته است، اما سردرآوردن از این‌که کار را از کجا شروع کنیم دشوار است. داده‌های مبادلاتی را می‌توان به‌روش‌های بی‌شماری، مثل خردکردن تکه‌ای کاغذ توسط قیچی، خرد، تکه‌تکه و گروه‌بندی کرد. کلید هر دو مورد بالا مسیر درست است.تصویر هالیوود از تحلیل داده‌هااجازه دهید یک تصویر معمولی هالیوود از تحلیل داده‌ها را برای‌تان توصیف کنم؛ مردی در برابر صفحه‌ی نمایش بزرگی ایستاده است و داده‌ها (دنباله‌ای از اعداد) در کل صفحه شناورند. این مرد الگوهایی موجود در داده‌های شناور را شناسایی می‌کند. این تصویری پرقدرت، اما کاملاً غیرواقعی است. روش خیره‌شدن به داده‌ها و امید به یافتن الگوها بی‌شک فقط نویز تولید می‌کند و سیگنال ناچیزی به‌دست ما می‌دهد. حتی کدشکن‌های بزرگی مثل جان نَش[6] و اَلن تورینگ[7] هم اگر بکوشند با استفاده از روش هالیوود الگوهای موجود در داده‌ها را بیابند، شکست می‌خورند.درواقع، منظورم این است که تحلیل داده‌ها، فعالیتی شدیداً برنامه‌ریزی‌شده‌ است. به‌عنوان تحلیل‌گر، هیچ‌گاه پیش از داشتن برنامه‌ی مناسب و آماده‌ای از اقدامات (فرضیه‌ها و غیره)، به داده‌ها دست نزنید. با این اوصاف، همیشه مواقعی هست که به‌عنوان تحلیل‌گر مجبور خواهید شد برای یافتن الگوها، به قلمروهای ناشناخته‌ای از داده‌ها وارد شوید. در چنین مواردی، توصیه می‌کنم به الگوریتم‌های یادگیری ماشین متکی باشید یا الگوریتم‌های تعدیل‌یافته‌ی خودتان را که مختص نیازهای‌تان هستند خلق کنید. به نظرم، ماشین‌ها در انجام این کار خیلی بهتر از ما انسان‌ها عمل می‌کنند. تحلیل وابستگی قدرت‌یافته توسط الگوریتم آپریوری[8] یکی از چندین روش‌ها برای استخراج داده‌های مبادلاتی است. اجازه دهید تحلیل وابستگی را در بخش بعدی بررسی کنیم.تحلیل وابستگیتحلیل وابستگی، همان‌طور که به‌زودی کشف خواهید کرد، تحلیل فراوانی[9] مقدماتی اجراشده روی مجموعه‌داد‌ه‌ای بزرگ است. از آنجایی‌که مجموعه‌داده‌های بیشتر مسائل عَملی بزرگ هستند، پس برای اجرای تحلیل وابسنگی به الگوریتم‌های هوشمندی مثل آپریوری نیاز دارید. اجازه دهید برای یادگیری تحلیل وابستگی، از مجموعه‌ داده‌ی خیلی کوچک‌تری شروع کنیم. در جدول زیر، هر ردیف یا عدد مبادله معرف سبدهای بازار مشتریان است. در ستون‌های بعدی کالاها، ۱ معرف «خرید کالا در آن مبادله» و ۰ معرف «عدم خرید» است.چندین متریک تحلیل وابستگی (یعنی پشتیبانی، اطمینان و ارتقاء) وجود دارد که در رمزگشایی اطلاعات نهفته در این نوع مجموعه‌داده بسیار مفیدند. بیایید این متریک‌ها را بررسی کنیم و کاربرد آنها را بشناسیم. پشتیبانی برای خرید پیراهن‌ها و کراوات‌ها با هم در تحلیل وابستگی به‌صورت زیر تعیین می‌شود:برای داده‌های ما، از کل ۵ مبادله، ۳ مبادله‌ مربوط به پیراهن‌ها و کراوات‌هااست:۶۰ درصد مقدار نسبتاً بالایی برای پشتیبانی است و به‌ندرت چنین مقادیر بالایی از پشتیبانی را در مثال‌های شرایط واقعی رؤیت می‌کنید. برای مشکلات شرایط واقعی با چندین دسته کالا، پشتیبانی ۱ درصد یا گاهی حتی کمتر، بسته به ماهیت مشکل‌تان، نیز مفید خواهد بود. اطمینان وابستگی با استفاده از فرمول زیر محاسبه می‌شود:در مجموعه‌داده‌ی ما، از ۴ مبادله‌ی پیراهن‌ها، ۳ مبادله مربوط به پیراهن‌ها و کراوات‌ها است. محاسبه‌ی اطمینان مجموعه‌داده‌ی ما به‌صورت زیر است:بار دیگر یادآوری می‌کنم که به‌ندرت چنین مقدار بالایی از اطمینان را برای بیشتر مشکلات واقعی خواهید یافت، مگر این‌که پیشنهادهای جذابی روی دو کالا داده شود. مقدار خوبی از اطمینان به‌طور خاص به مشکل یافت  می شود.  سومین متریک مفید تحلیل وابستگی ارتقاء است که به‌صورت زیر تعیین می‌شود:اطمینان موردانتظار در فرمول بالا، موجودی کراوات‌ها در مجموعه‌داده‌ی کل است؛ یعنی از ۵ خرید، ۴ مورد خرید کراوات است.مقدار ۱۲۵ درصدی ارتقاء نشان می‌دهد زمانی‌که مشتریان پیراهن می‌خرند، خرید کراوات بهبود می‌یابد. سؤالی که اینجا برای‌تان پیش می‌آید این است که اگر مشتری یک پیراهن بخرد، آیا احتمال خرید کراوات توسط این مشتری بالا می‌رود؛ یعنی مقدار ارتقاء بالاتر از ۱۰۰ درصد. بیایید از دانش تحلیل وابستگی‌مان در مثال مطالعه‌ی موردی‌ای که روی آن کار می‌کردیم استفاده کنیم.مثال مطالعه‌ی موردی خرده‌فروشی – تحلیل پیوستگیشرکت درس‌اسمارت، شرکتی که شما مدیر ارشد تحلیل و رئیس راهبرد کسب‌وکارش هستید، فروشگاه خرده‌فروشی آنلاین عرضه‌کننده‌ی پوشاک است. این شرکت کالاها، برندها و سبک‌های مختلفی عرضه می‌کند. می‌‌دانید که تحلیل وابستگی زمانی بهترین کارکرد را دارد که روی گروه‌های مختلف مشتریان به‌طور مجزا اجرا شود (راجع به گروه‌بندی مشتری[10] مطالعه کنید). هرچند، تصمیم گرفته‌اید تحلیل وابستگی سریعی روی داده‌های موجود در شرکت‌تان اجرا کنید.با داده‌های مربوط به پیراهن‌های رسمی و کراوات‌ها که در مثال بالا بررسی کردیم، پشتیبانی ۰.۲ درصد، اطمینان ۱۲ درصد و ارتقاء ۵۰۹ درصد حاصل شد. این ارقام نشان می‌دهند که گرچه درصد رکوردهای پایین‌تری از مبادلات برای کراوات‌ها و پیراهن‌ها وجود دارد، اما به‌مجرد این‌که مشتری پیراهن‌های رسمی بخرد، احتمال خرید کراواتش تا پنج برابر افزایش می‌یابد.درس‌اسمارت گزینه‌ی بازگرداندن کالا را برای مشتریانش مهیا کرده است. کالاهای آسیب‌ندیده‌ای که ظرف ۳۰ روز بازگردانده می‌شوند، هزینه‌ی کامل‌شان به مشتری پس داده می‌شود. در ادامه، مشتریانی را بررسی کردید که علاوه بر پیراهن، کراوات هم می‌خرند و دریافتید که نرخ‌های بازگشت کالای کراوات برای آن مبادلات نیز ۳ برابر بیشتر از سایر نرخ‌های بازگشت است. این نشانگر آن است که مشتریان در انتخاب کراوات‌های مناسب، هنگام سفارش‌ آنلاین آنها به‌همراه پیراهن مشکل دارند. نیازی به بهبودبخشیدن این فرایند روی وب‌سایت شرکت نیست. هدف کاهش نرخ بازگشت کالا، ضمن بهره‌گیری کامل از فرصت مهیاشده برای فروش مکمل کراوات‌ها با پیراهن‌ها است.چندین سرنخ خوب پیدا کردید تا بتوانید سودآوری شرکت‌تان را از طریق ابزارهای تحلیل کاوشگرانه‌ی داده‌ها بهبود بخشید. حالا می‌خواهید اهداف اصلی را آماده و مطرح کنید (بخش ۲) تا سودآوری اقدامات کمپین را ارتقاء دهید. دفعه‌ی بعد، مدل‌سازی جدی این کار را به‌طور دقیق بررسی خواهید کرد.و اما حرف آخرامیدواریم هنگام کارکردن با داده‌های‌تان، از ایفای نقش ادوارد دست‌قیچی لذت ببرید! به‌زودی در بخش بعدی، مثال مطالعه‌ی موردی از سری مقالات تحلیل بازاریابیِ خرده‌فروشی‌ دایکه، جایی‌که بیشتر راجع به الگوریتم‌های درخت تصمیم کاوش می‌کنیم، شما را ملاقات خواهیم کرد![1] market basket analysis[2] sequence analysis[3] Scissorhands[4] Socially Useful Productive Work[5] Some Useful Paper Wasted[6] John Nash[7] Alan Turing[8] Apriori algorithm[9] frequency analysis[10] customer segmentation</description>
                <category>نشریه دایکه</category>
                <author>dayche-group</author>
                <pubDate>Tue, 08 Oct 2019 12:11:01 +0330</pubDate>
            </item>
                    <item>
                <title>تحلیل بازاریابیِ خرده‌فروشی‌ها – بخش سوم</title>
                <link>https://virgool.io/dayche-group-Blog/%D8%AA%D8%AD%D9%84%DB%8C%D9%84-%D8%A8%D8%A7%D8%B2%D8%A7%D8%B1%DB%8C%D8%A7%D8%A8%DB%8C%D9%90-%D8%AE%D8%B1%D8%AF%D9%87%D9%81%D8%B1%D9%88%D8%B4%DB%8C%D9%87%D8%A7-%D8%A8%D8%AE%D8%B4-%D8%B3%D9%88%D9%85-jkcvedll1rja</link>
                <description>طی چند هفته‌ی گذشته، داشتیم روی مثال مطالعه‌ی موردی تحلیل‌های بازاریابی (بخش‌ ۱ و بخش‌ ۲ از سری مقالات تحلیل بازاریابیِ خرده‌فروشی‌ دایکه را مطالعه کنید) کار می‌کردیم. در بخش پایانی (بخش ۲)، چندین هدف تحلیلی پیشرفته را برمبنای مشکل کسب‌وکار موجود در شرکت آنلاین خرده‌فروشی‌ای به‌نام شرکت درس‌اسمارت[1] تعریف کردیم. در این بخش، تعدادی از تحلیل‌های کاوشگرانه‌ی داده‌ها را به‌عنوان بخشی از مثال موردی مشابه اجرا می‌کنیم. اما پیش از اجرای این تحلیل‌ها اجازه دهید قدرت تحلیل کاوشگرانه‌ی داده‌ها ( [2] EDA) را به‌منظور افشای حقایق پنهان مربوط به مهم‌ترین بازی دنیا، یعنی فوتبال بررسی کنیم.فوتبال – تحلیل کاوشگرانه‌ی داده‌هافوتبال بی‌شک محبوب‌ترین بازی دنیا است و بیش از ۲۰۰ کشور تیم فوتبال رسمی خودشان را دارند. هیچ بازی دیگری از چنین جذابیت جهانی و میلیون‌ها طرفدار پروپاقرص برخوردار نیست. تمامی جزئیات فوتبال توسط بازیکنان، مربیان و کادر پشتیبانی تحلیل می‌شوند. با این‌وجود، همان‌طور که در دو مثال مطالعه‌ی موردی بعدی خواهید دید، تحلیل کاوشگرانه‌ی دقیق داده‌های بازی می‌تواند رمز و رازهای بُرد مسابقه را راجع به مهمترین بازی جهان افشا کند.ضربات پنالتیبیایید اولین مسابقه‌ی حذفی (پیش از مرحله‌ی نهایی) جام جهانی فوتبال ۲۰۱۴ بین برزیل و شیلی را مرور کنیم. نتیجه‌ی ‌این مسابقه در پایان ۹۰ دقیقه ۱-۱ بود. حتی یک ساعت وقت اضافی هم نتوانست نتیجه را عوض کند. همین باعث شد بازی به ضربات پنالتی کشیده شود تا این تساوی بالاخره بشکند. پس از این‌که بازیکن برزیلی، نیمار[3]، پنالتی یکی مانده به آخر را گل کرد، برزیل ۳-۲ در ضربات پنالتی جلو افتاد. شیلی هنوز یک ضربه‌ی پنالتی داشت که گونزالو جارا[4] زننده‌ی آن بود؛ پس شیلی فرصت داشت نتیجه‌ی تساوی را همچنان پیش ببرد. اما اگر این ضربه گل نمی‌شد، شیلی از مسابقه حذف می‌شد. پس گونزالو جارا چه باید می‌کرد تا تساوی همچنان پابرجا می‌ماند؟در این سطح، به‌طور متوسط حدود ۷۵ درصد از ضربات پنالتی گل می‌شوند. با این حساب، احتمالات شدیداً به نفع گونزالو جارا هستند. گونزالو جارا توپ را کجای دروازه باید شوت کند تا احتمالات را بهبود بخشد؟ همه‌ی طرفداران، مربیان و بازیکنان می‌گویند توپ را به سمت یکی از گوشه‌های دروازه، دور از دسترس دروازه‌بانی که در وسط دروازه ایستاده است شوت کن. همچنین برخی توصیه می‌کنند که هرگز توپ را مستقیماً به سوی مرکز بسته‌ی سمت دروازه‌بان شوت نکن. گروهی از محققان پرسش‌های مشابهی را مطرح و تحلیل کاوشگرانه‌ی داده‌های ضربات پنالتی را در سطح سرآمدی از فوتبال اجرا کردند. دروازه‌بانان، زمانی‌که توپ با سرعت پیش‌بینی‌ناپذیری به سمت‌شان شوت می‌شود، معمولاً برحسب غریزه عمل می‌کنند؛ یا به سمت چپ‌شان (۵۷ درصد از مواقع) یا به سمت راست‌شان (۴۱ درصد مواقع) شیرجه می‌زنند. این باعث می‌شود فقط ۲ درصد از مواقع برای گرفتن توپی که به سمت‌شان پرتاپ می‌شود در مرکز دروازه باشند. بنابراین، ضربه‌ی دقیق به سمت مرکز دروازه، در مقایسه با ضربات به یکی از گوشه‌ها در ارتفاع یکسان، شانس بسیار بالایی برای گل‌شدن دارد.به گونزالو جارا برمی‌گردیم؛ او توپ را به سمت راستش شوت می‌کند، یعنی در مسیر شیرجه‌زنی دروازه بان (شکل بالا). ضربه‌ی او گل نمی‌شود، توپ به تیر دروازه برخورد می‌کند و از دروازه دور می‌شود. به این ترتیب، شیلی از مسابقات جام جهانی حذف و برزیل وارد مرحله‌ی بعدی شد. در دفاع از گونزالو جارا باید بگوییم که نرخ گل‌شدن ضربات پنالتی بحرانی‌ای مثل این مورد (برای اجتناب از حذف‌ شدن) ۴۴ درصد افت دارد. بله!‌ فشار غول دیگری است که حتی بهترین‌ها هم دربرابرش تسلیم می‌شوند.ضربات کُرنردر موردی دیگر، چندین سال پیش تیم فوتبال منچستر سیتی[5] با ضربات کرنر مشکل داشت و بنابراین، تصمیم گرفت تحلیل کاوشگرانه داده‌ای انجام دهد تا ضربات کرنر نتیجه‌بخش را از ضربات کرنر بی‌نتیجه متمایز کند. تیمی از تحلیل‌گران، صدها ویدئوی ضربات کرنر مربوط به لیگ برتر را تحلیل کردند. آنها پس از تکمیل تحلیل دریافتند که ضربات چرخشی به سمت دروازه بسیار نتیجه‌بخش‌تر و خطرناک‌تر از ضربات غیرچرخشی بودند. آنها نتایج‌شان را به روبرتو مانیچی[6]، مربی تیم منچستر سیتی در آن زمان، ارائه دادند. مانیچی، که از کودکی فوتبال بازی و دنبال می‌کرده است، این یافته‌ها را به‌کلی رد کرد. او همه‌ی گل‌های به‌یادماندنی و بی‌نقص توسط سرزن‌های شوت‌های غیرچرخشی را یادآوری کرد. از سوی دیگر، گل‌های ناشیانه‌ی شوت‌های چرخشی نتوانسته بودند خاطره‌ی ماندگاری در ذهن تماشاچیان حک کنند. از قرار معلوم، مانیچی اشتباه می‌کرد. شوت‌هایی که فوق‌العاده و به‌یادماندنی به‌نظر می‌رسند، همیشه هم بهینه نیستند. این مورد به‌خوبی ثابت می‌کند که تحلیل کاوشگرانه‌ی داده‌ها چطور به‌سادگی اما صادقانه می‌تواند باورهای عمیقاً‌ ریشه‌داری که طی قرن‌ها شکل گرفته‌اند را به چالش بکشد (بله!‌ فوتبال واقعاً‌ یک بازی قدیمی‌ است).تحلیل کاوشگرانه‌ی داده‌ها – مثال مطالعه‌ی موردی خرده‌فروشیبه مثال مطالعه‌ی موردی‌مان برمی‌گردیم (بخش‌ ۱ و بخش‌ ۲ را مطالعه کنید)؛ در این مثال، شما مدیر ارشد تحلیل و رئیس راهبرد کسب‌وکار در فروشگاه آنلاینی به‌نام شرکت درس‌اسمارت هستید. شما در ارتقاء نتایج کمپین‌های شرکت به مدیرعامل کمک می‌کنید. طی چند روز گذشته، به‌عنوان بخشی از تحلیل کاوشگرانه‌ی داده‌ها، با داده‌ها ور می‌روید. گراف زیر یکی از چندین الگو و نتیجه‌ی جالبی است که در داده‌ها یافته‌اید. زمانی‌که توزیع مشتریان در تعدادی از دسته‌های کالاها (پیراهن مردانه، شلوارهای غیررسمی، دامن‌های رسمی و غیره) خریداری‌شده توسط هر مشتری را تحلیل می‌کنید، به الگوی زیر می‌رسید.توزیع فوق کمابیش شبیه توزیع پیش‌بینی‌شده است. هرچند، پیک جالبی برای مشتریانی که بیش از ۵۰ دسته کالا می‌خرند دیده می‌شود. این مشتریان چه کسانی هستند؟ چرا این همه کالا می‌خرند؟ در ادامه، این گروه از مشتریان را تحلیل می‌کنید و درمی‌یابید که نرخ رشدشان بالاتر از سایر گروه مشتریان است. از زمان شروع فعالیت ۷ سال پیش شرکت، درصد مشتریانی که بیش از ۵۰ دسته کالا در سال خریداری می‌کنند به‌طور نمایی افزایش یافته است (در حال حاضر، ۲.۱ درصد). این گروه از مشتریان در ۲۳ درصد از کل فروش شرکت درس‌اسمارت نیز مشارکت می‌کنند. گراف‌های زیر بخشی از تحلیل فوق هستند.خُب، اینجا چه خبر است؟ در ادامه، الگوها و اندازه(های) پوشاکی که این مشتریان می‌خرند را تحلیل کردید و متوجه شدید که آنها سبک مشابه با سایزهای مختلف را می‌خرند. خب!‌ حالا این مشتریان را می‌شناسید، اینها خرده‌فروشان مجاور کوچکی هستند که از درس‌اسمارت به‌عنوان عمده‌فروش استفاده می‌کنند.۱. ارسال کاتالوگ و کمپین خرده‌فروشی مشابه مشتریان خرده‌فروشی به این خرده‌فروشان منطقی نیست.۲. فرصتی برای تقویت روابط تجاری با این خرده‌فروشان خانوادگی و بدین ترتیب، ارتقاء سودآوری شرکت‌تان از طریق برنامه‌ی کسب‌وکار مجزایی وجود دارد.به‌علاوه، تحلیل بیشتر نشان داد که الگوهای تحویل یا تکمیل سفارش (کمیت تحویل/ مطالبه‌کنندگان و غیره) برای این خرده‌فروشان با مشتریان دیگر یکی است. شرکت شما، در زمان تحویل، از این مشتریان هزینه‌ی اضافی می‌گیرد. با حفظ این خرده‌فروشان کوچک در معادله، می‌توانید زنجیره‌ی تأمین کلی را بهتر طرح‌ریزی کنید. این تحلیل کاوشگرانه‌ی داده‌ها، ایده‌های خوبی برای دستیابی به اهداف سهل‌الوصول‌تر به‌منظور ارتقاء سودآوری شرکت‌تان ارائه می‌دهد.و اما حرف آخرتحلیل کاوشگرانه‌ی داده‌ها ابزار قدرتمندی است. EDA ضرورت مسلمی برای سوق‌دادن تحلیل‌های پیشرفته‌ی کسب‌وکارتان در مسیر درست است. EDA فرصت فوق‌العاده‌ای برای آزمودن ساده‌ترین فرضیه‌ها و حدسیات کسب‌وکارتان، پیش از پیشروی سریع به‌سوی ساختن مدلی دقیق، مهیا می‌کند. به فوتبال بازمی‌گردیم؛‌ کماکان به مراحل پایانی جام جهانی نزدیک می‌شویم. از چند بازی نهایی لذت ببرید و باشد که بهترین تیم جام را از آن خود کند.[1] DresSmart Inc[2] Exploratory Data Analysis[3] Neymar[4] Gonzalo Jara[5] Manchester City[6] Roberto Mancini</description>
                <category>نشریه دایکه</category>
                <author>dayche-group</author>
                <pubDate>Tue, 08 Oct 2019 11:42:48 +0330</pubDate>
            </item>
                    <item>
                <title>تحلیل بازاریابیِ خرده‌فروشی‌ها – بخش دوم</title>
                <link>https://virgool.io/dayche-group-Blog/%D8%AA%D8%AD%D9%84%DB%8C%D9%84-%D8%A8%D8%A7%D8%B2%D8%A7%D8%B1%DB%8C%D8%A7%D8%A8%DB%8C%D9%90-%D8%AE%D8%B1%D8%AF%D9%87%D9%81%D8%B1%D9%88%D8%B4%DB%8C%D9%87%D8%A7-%D8%A8%D8%AE%D8%B4-%D8%AF%D9%88%D9%85-vflphhspfzh3</link>
                <description>در مقاله قبلی، ما مطالعه روی موسسه خرده فروشی آنلاین را به منظور یادگیری بیشتر درمورد تجزیه و تحلیل بازاریابی شروع کردیم (بخش اول از  سری مقالات تحلیل بازاریابیِ خرده‌فروشی‌ دایکه را بخوانید). قبل از اینکه  همین مورد را ادامه دهیم، اجازه بدید من چند فاکتور مهم که کیفیت تحلیل  برای بازاریابی یا تحلیل مشتری را افزایش می دهد بازگو کنم. فاکتورهای  بسیار واضح عبارت اند از گرایش و خبرگی در حل کردن مشکلات کسب و کار و همینطور عشق به داده، ریاضیات و اعداد. علاوه بر این، برای درک و شناخت بهتر مشتریان، تحلیل‌گران باید مشتاق به درک رفتار انسان باشند. شاخه‌های اصلی از علوم که فهم ما از چرایی رفتار انسان را افزایش میدهند، روانشناسی، جامعه شناسی و علوم اعصاب می باشند.روانشناسی مطالعه روی رفتارهای انفرادی است درحالیکه جامعه شناسی روی رفتارهای اجتماعی انسان ها تمرکز دارد. علم اعصاب نیز در دهه ی گذشته بازی را در دست گرفته و فهم ما از رفتار و مغز انسان را دگرگون ساخته است. تکنیک های تصویربرداری پیشرفته نظیر fMRI در  مورد مناطق غیرقابل دسترس مغز و کاربردهایش توضیح می دهد. البته این‌ها  هنوز در مراحل اولیه خود هستند، اما ما در زمان هیجان انگیزی زندگی می‌کنیم  که در آن چیزهای بامزه‌ی زیادی در مورد رفتار انسان‌ها یاد می‌گیریم. خب  اجازه دهید در مورد رفتار انسان‌ها بواسطه‌ی تجزیه و تحلیل، کمی بیشتر  واکاوی کنیم. همچنین راجع به انحرافات رفتاری…!عصب شناسی آدمکشقتل، جنایت هولناکی است. اکثر آدم‌کش های فجیع یا قاتل‌های سریالی بودند  یا روانپریش‌ها! این قانون‌گریزان، در جامعه ما به عنوان مجرمینی شناخته  می‌شوند که دو یا چند قربانی را در رخدادهای مجزایی به قتل رسانده اند.  بدترین قاتل‌های سریالی مثل Ted Bundy بیش از ۳۰ قربانی را به قتل رسانده  که همگی ناشناس و بدون دلیل خاصی بودند. روانپریشان اغلب چنین رفتارهایی را  بخاطر عدم همدلی، ضعف در کنترل شخصیت و خطر ابتلا به افسردگی از  خود نشان میدهند. اجازه دهید برای فهم عمیق چنین رفتارهایی نظیر عدم همدلی  و ضعف در کنترل شخصیت، نگاهی به مغز و عملکرد آن داشته باشیم و در ادامه  رفتارهای دیگر را هم بررسی خواهیم کرد. این فرآیند در یادگیری بیشتر در  مورد رفتار انسان، به ما کمک می‌کند.آخرین  سکانس از فیلم تایتانیک را بخاطر بیاورید، زمانی که لئوناردو دیکاپریو (در  نقش جک) در حال مرگ در اقیانوس آتلانتیک بود. در این سکانس جک از دوست  دخترش رُز درخواست می‌کند که زندگی بلند و شادی داشته باشد. این سکانس بعضی  از مردم را به گریه انداخت و خیلی از تماشاگران عمیقا درگیر این رخداد  ناگوار شدند. این تمایل انسان به ارتباط و حس کردن درد مردمان دیگر و یا  شادی‌شان را همدلی می نامند. بی شک بازاریابان از این واقعیت آگاه بودند و  از تاثیرگذاری آن در تبلیغات بخاطر ایجاد احساس عمیق تر و ارتباط مشتری با  محصولشان استفاده کردند.افراد روانپریش و قاتلان سریالی این حس همدلی را ندارند. به همین دلیل  به راحتی میتوانند قربانی خود را تا حد مرگ شکنجه دهند و از تماشای آن لذت  ببرند. عدم همدلی در روانپریشان به دلیل اختلال نورولوجیکال (عصبی) در مغز  آنها رخ می‌دهد. نورون‌های آینه (بخشی از مدار پیچیده و مفصل از شبکه های  عصبی مغز) مراکز احساسی مغز را به اندام های حسی نظیر چشم متصل می‌کنند.  مدارهای مربوط به نورون های آینه در افراد روانپریش دچار اختلال می‌شود، از  این رو مراکز عاطفی مغز آنها دیگر به اندازه کافی نسبت به درد افراد دیگر  حساسیت نشان نمی‌دهد.بخش  مهمی از مغز انسان که مسئول احساسات ماست، لوب پیشانی است (بله خودم کاملا  متوجه هستم که از اصطلاحات زیادی در اینجا استفاده میکنم، اما این بخش از  مغز واقعا جالب است، بعدا در مورد لوب پیشانی بیشتر هم صحبت خواهیم کرد).  لوب پیشانی همچنین وظیفه خودآگاهی و کنترل شخصی را بر  عهده دارد. در بیماران روانی لوب پیشانی فعالیت کمتری نسبت به مغز انسان  عادی دارد. از این رو فقدان کنترل شخصی در این گونه افراد به وفور دیده  می‌شود. بازاریابان و تبلیغ‌کنندگان،  اغلب کنترل شخصی مخاطبان خود را در پیام‌های جذاب و تکنیک های بصری  بازاریابی، مورد بررسی و هدف قرار می‌دهند. همه‌ی ما در مقاطع مختلفی از  زندگی‌مان محصولاتی را خریدیم که به آن‌ها نیاز نداشتیم و بخاطر عدم کنترل  شخصی متقاعد به خرید شده‌ایم! این که عصب شناسی چطور رفتار ما را به فعالیت  های مغزمان پیوند میزند موضوع جالب توجهی است.برگردیم به قاتل های سریالی. در ادبیات مدلسازی و تحلیل، فاکتورها و  متغیرهای کلیدی برای شناسایی فعالیت های نابجا، هم به طبیعت (یعنی ژنتیک،  فعالیت های مغزی و…) وابسته است و هم به پرورش (نوع تربیت، رفتار والدین،  رفتار جامعه و…). این جمله از فرانسیس کالینز (مدیر NIH) نقش ژنتیک و جامعه  را برای بوجود آمدن قاتلان بخوبی شرح داده است:ژنتیک اسلحه را پر می‌کند و طبیعت ماشه را می‌کشد!رفتار انسانی بسیار پیچیده است، چرا که ترکیبی از  فاکتورها و متغیرهای بسیار زیادی است. برای تحلیلگران بازاریابی، این یک  ضرورت است که نسبت به رفتار انسان هوشیار و تیزبین باشند. وظیفه تحلیلگر  بازاریابی فقط محاسبه اعداد نیست، بلکه باید درک عمیقی از رفتار مشتری داشته باشد. یک تحلیلگر بازاریابی همچنین نباید فقط بگوید مشتری چگونه  رفتار میکند، بلکه باید در مورد چرایی رفتار مشتری در موقعیتی که قرار  می‌گیرد هم صحبت کند. اینها رو توی ذهنتون داشته باشید، و برگردیم به  مطالعه تجزیه و تحلیل بازاریابی که در مقاله قبلی دایکه شروع کردیم؛مثال برای تجزیه و تحلیل بازاریابیبعد از اینکه CMO از اتاق شما بیرون رفت (مقاله قبلی را  مطالعه کنید)، از تحلیلگرانتان خواستید تا چند عدد از انباره  داده شرکت  برای سود و هزینه کمپین را بیرون بکشند. با استفاده از داده ها شما متوجه  شدید متغیر هزینه اجرای یک کمپین برای هر درخواست چیزی حدود ۲٫۳$ است.  علاوه بر این، هر مشتری که از کاتالوگ بازاریابی استفاده میکند سودی حدود  ۵۶$ بوجود میاورد. شما هم پشت یه برگه سریعا سود حاصل از کمپین را محاسبه  کردید.الان می توانید ابعاد مسئله را در تراز سود و زیان بالا ببینید. در  محاسبات خط پایانی هیچ حاشیه سود مناسبی برای هزینه کرد اجرایی کمپین ها  برای CMO  باقی نمی‌ماند و بایستی در دو مورد بهتر کار کرد: نرخ پاسخ/تبدیل  کمپین و درآمدی که از مشتریان بدست می آید. این امر به شما کمک می کند تا  سریعا به شناسایی اهداف دست یابید؛ مثل :هدف اول نرخ تبدیل کمپین ها (تعداد مشتریانی که پس از ارائه کاتالوگ اقدام به خرید می کنند)  را افزایش دهیمهدف دوم افزایش درآمدی که از مشتریان بدست می آیداهداف بالا باعث به وجود آمدن دو مدل می شود، مدل اول ارزیابی امکانات  برای مشتریان در جهت پاسخ به کاتالوگ کمپین از طریق خرید محصولات، مدل دوم  تخمین میزان دلاری که هرمشتری خرج می کندهمانطور که پیداست مشکل مدل اول دسته‌بندی و مشکل مدل دوم تخمین زدن  میزان دلار به صورت متوالی است. پس از تلاش هایی که کمپین برای رضایت بخشی ۲  هدف بالا انجام داده است، سود خالص باید بیشتر از ۵۲۰۰ دلار باشد. در  مقالات بعدی دایکه،  بیشتر روند انجام این اهداف فوق را بررسی خواهیم کرد.و اما حرف آخرما تا اینجا شاهد آن بودیم که روانپریشان و قانون‌گریزان الگوهای رفتاری ای نظیر عدم همدلی، کنترل شخصی ضعیف، خطر ابتلا به افسردگی، غرور و … را دارند. با این حال بایستی اشاره کنم که هرکس که تمایلات مذکور را داشته باشد الزاما قاتل سریالی نخواهد شد،  مثال های بسیاری هست از مردمی با ساختار مغزی مشابه با روانپریشان که در  جامعه با شرافت رفتار می‌کنند. البته که پرورش خوب (تربیت والدین، پشتیبانی  جامعه و…) شخصیت آنها را به گونه ای شکل داده است که نسبت به جامعه درست  رفتار کنند.</description>
                <category>نشریه دایکه</category>
                <author>dayche-group</author>
                <pubDate>Sat, 05 Oct 2019 18:10:17 +0330</pubDate>
            </item>
                    <item>
                <title>تحلیل بازاریابیِ خرده‌فروشی‌ها – بخش اول</title>
                <link>https://virgool.io/dayche-group-Blog/%D8%AA%D8%AD%D9%84%DB%8C%D9%84-%D8%A8%D8%A7%D8%B2%D8%A7%D8%B1%DB%8C%D8%A7%D8%A8%DB%8C%D9%90-%D8%AE%D8%B1%D8%AF%D9%87%D9%81%D8%B1%D9%88%D8%B4%DB%8C%D9%87%D8%A7-%D8%A8%D8%AE%D8%B4-%D8%A7%D9%88%D9%84-naappxjjgx71</link>
                <description>قصد داریم مقالاتِ کاربردیِ جدیدی  از مقالات سریالی وبسایت ucananalytics رو، در این بخش استارت بزنیم. در  سری اول، وجه های مختلفی از تجزیه و تحلیل بازاریابی و مدیریت ارتباط با مشتری (CRM) رو ارزیابی می‌کنیم. از مثال خرده فروشی آنلاین که حوزه پرمخاطبی است، برای بیان بهتر جزئیات این نوع تحلیل استفاده خواهیم کرد.مقدمهدر این قسمت از سری مقالات تجزیه و تحلیل بازاریابی، ما در مورد شناسایی فرصت های افزایش فروش در بین مشتریان کنونی صحبت کرده و آزمایش هایی را برای یادگیری در مورد مدیریت کمپین ها طراحی خواهیم کرد. همچنین روش های علمی دیگری را برای کسب اطلاعات بیشتر در مورد مشتری،  بمنظور سازمان‌دهی و تقویت روابط تجاری خود با مشتری های موجود، بررسی  می‌کنیم. اما پیش از شروع نیاز داریم تا کمی بیشتر بدانیم… تا انتهای این  قسمت همراه دایکه باشید.انگیزه ها و تاثیراتخب، در این بخش از مقاله، من برای شما یک وظیفه در نظر گرفتم. فرض کنید  که شما از مردم می‌خواهید با جایگزین کردن کولرهای گازی با پنکه های سقفی،  مصرف برقشان را کاهش دهند. من در زیر لیستی از دلایلی را که شما برای  متقاعد کردن آنها بواسطه تبلیغاتتان به کار می‌برید آماده کردم. فکر می  کنید به ترتیب کدام یک از دلایل زیر بیشترین تاثیر را بر مردم خواهد داشت؟!منفعت جامعه: انتقال برق ذخیره شده به مناطق محروم در جامعه.پسنداز پول: کاهش هزینه‌ی قبض های برق.پیروی از جامعه: همه این کار را انجام می‌دهند و بهتره شما هم انجام بدید.حفظ محیط زیست: کاهش بار تولید برق در محیط زیست بمنظور حفظ آن.اگر سوال را متوجه نشدید یکبار دیگر از اول بخوانید. سوال بالا بخشی از  تحقیق انجام شده توسط دکتر Robert Cialdini نویسنده کتاب پرفروش “نتایج:  روانشناسی متقاعد کردن” می‌باشد. دکتر رابرت چیالدینی یک نظرسنجی انجام داد  و از مردم سوال مشابهی در مورد اینکه چه فاکتورهایی (موارد بالا) در تحریک  آنها برای ذخیره برق موثر است پرسید. در ادامه نتایج این نظرسنجی تلفنی  ذکر شده است:“حفظ محیط زیست” در رده اول قرار گرفت و بعد از اون به ترتیب “منفعت جامعه” و “پسنداز پول” در رده دوم و سوم و “پیروی از بقیه”  در انتهای لیست تاثیر گذاری روی عموم بمنظور کاهش مصرف برق قرار گرفتند.  در این نظرسنجی، ترتیب پاسخگویی افراد مهم بوده است. نتیجه‌ی بدست آمده از  تحقیق ذکر شده، این حساسیت را ایجاد میکند که چه کسانی میخواهند همرنگ  جماعت باشند؟ ما همه در اندیشیدن آزاد هستیم، اینطور نیست؟ اما سوال اساسی  این است که آیا مردم همانطور رفتار میکنند که خودشان میپندارند؟!برای آزمایش اینکه مردم پولشان را آنجایی که باید خرج می‌کنند یا نه، او  یکی از چهار دلیل کم مصرفی را بعنوان پیامی روی دستگیره درب خانه های مردم  گذاشت، سپس الگوهای مصرفی برق این افراد را بدقت زیر نظر گرفت، نتایج شگفت  آور بود. گروهی که پیام “پیروی از دیگران” را دریافت کرده بودند، بهتر از  هر گروه دیگر مصرف برق را کاهش داده بودند.ریشه‌ی موفقیت استراتژیِ “پیروی از دیگران”، در سیر تکاملی است. از دیدگاه تکاملی، دیدگاهِ “پیروی از دیگران”، استراتژی برتری برای بقا، نسبت به بقیه‌ی استراتژی هاست.یک انسان بدوی را که در وضعیت دشوار انتخاب یک مسیر درست از دو مسیر پیش  رویش است، تصور کنید. یکی از جاده ها خوش مسیر و امن است، و از دیگری  اطلاعات بسیار کمی موجود است. در مسیر جاده ای که کمتر طی شده است ریسک بالایی وجود دارد، و از نقطه نظر تکاملی ریسک پذیری اقدامی نابجا بحساب می‌آید. اگر همچنان نسبت به نتیجه ی تحقیق دکتر چیالدینی و بحث  تکامل قانع نشدید، بخاطر بیاورید که مردم، چگونه صحنه‌ی یک تصادف یا یک  نزاع را به تماشا می‌ ایستند!تجزیه و تحلیل بازاریابیچه دوست داشته باشیم و چه نداشته باشیم، خیلی وقتها به بطور ناخواسته شبیه آدم های اطرافمان رفتار می‌کنیم. ما همه الگوهای غیرارادی ای را دنبال میکنیم و شناسایی این الگوها دقیقا همان ایده ای است که در پشت “تجزیه و تحلیل بازاریابی”  است. اگر همسایه کناری شما یک ماشین جدید بخرد، شما هم بلافاصله نسبت به  خرید ماشین جدید تمایل پیدا می‌کنید. ممکن است باور نکنید که ما چگونه در  کنار این وسوسه های غیرارادی زندگی می‌کنیم که غالبا هم تسلیمشان می‌شویم.  وظیفه تجزیه و تحلیل بازاریابی، شناخت گروه هایی با خصوصیت های مشابه است تا در مورد آنها بیشتر بیاموزد. این روش را همچنین “مدلسازی بر پایه  شباهت” می‌نامند. این به کسب و کارهای تجاری کمک میکند تا استراتژی های  بازاریابی برای گروه های مختلفی از مردم بر پایه‌ی نیازهایشان و الگوی مصرفشان ایجاد کنند.برای درک سریع تر کارکردهای تجزیه و تحلیل بازاریابی، این شماتیک را ملاحظه کنید. شما با گروه مشتری های ناشناخته شروع می‌کنید و سپس با استفاده از فرایند داده‌کاوی و ابزارهای آماری پیشرفته، سعی در شناسایی الگوهای پنهان اما جالب توجه در رفتار مصرفی مشتری می‌کنید. در نهایت دانش تجاری و قوانین بدست آمده را برای کلاس بندی قرار  می‌دهید تا با فرموله کردن استراتژی تجاری و بازاریابی به رشد تجارت کمک  کنید.در ادامه ی مقاله درک بهتری از فرایند بالا بدست خواهیم آورد.مثال برای تجزیه و تحلیل بازاریابیفرض کنید اخیرا بعنوان رئیس بخش تحلیلی و استراتژی تجاری در یک شرکت  فروشگاهی تجاری آنلاین بنام DresSMart استخدام شده اید. این فروشگاه بطور  تخصصی در بخش لباس و پوشاک فعالیت میکند. یک روز رئیس بخش بازاریابی شرکت  بطور سراسیمه‌ای وارد دفتر شما می‌شود. هیئت مدیره اهداف سنگینی برای فروش  به گردن او گذاشته است و در عین حال بودجه بخش بازاریابی را به نصف کاهش  داده اند. شما هم سریعا متوجه می‌شوید که دقیقا روی چنین مشکل تجاری ای  (یعنی افزایش درآمد با کاهش هزینه ها) کار می‌کنید و این فرصت بسیار مناسبی  است که آزمایشات تحلیلی‌تان را در شرکت پیاده کنید. چرا که این یک فرصت  مناسب برای اجرای سریع تراز سود و زیان کمپین است!علاوه بر این، مدیر اداره بازاریابی(CMO) به شما اطلاع می‌دهد که سال  گذشته کمپین های بازاریابی با آفرهای مختلفی در کاتالوگ محصولات انجام داده  اند. کاتالوگ محصولات برای چند صد هزار نفر از مشتریان بطور مستقیم ارسال  شد، این جمعیت از بین چند میلیون مشتری سال گذشته انتخاب شده بودند که ضریب  پاسخگویی ۴٫۲ درصد داشتند. برای توضیح سریع استراتژی‌تان به CMO، سریعا  روی تخته ی دفترتان تراز سود و ضرر کمپین را می‌کشید. عکس زیر هم نسخه ای  از آن چیزی است که شما کشیده اید:هدف اصلی به حداکثر رساندن ارزش انباشته ی تولید شده  بواسطه مشتری و در عین حال به حداقل رساندن هزینه نهایی پست کردن می‌باشد.  شما توضیح می‌دهید که تجزیه و تحلیل روی اجزای متغیر کمپین اثر می‌گذارد.  بعبارت دیگر، شما با نزدیک شدن به مجموعه ی درستی از مشتریان، بیشترین ارزش ممکن را تولید می‌کنید. بعلاوه اینکار یک منفعت پنهان دیگر هم دارد و نارضایتی خیلی از مشتریان را بخاطر آفرهای ناخواسته،  کاهش می‌دهد. مدیرتان، دفتر شما را ترک میکند و البته دیگر آن چهره مضطرب  را ندارد، و شما می‌فهمید که کارتان را انجام داده‌اید و الان باید در مورد  مسیر درست حل این مشکل فکر کنید. پس خودتان رو برای این چالش جدید آماده  می‌کنید!و اما حرف آخربرگردیم به انگیزه ها و نتایج؛ شما انگیزه کافی برای کار روی مشکل بالا را دارید، چرا که اینکار موقعیت شما را هم تثبیت می‌کند. بعلاوه، شما با افزایش درامد شرکت روی افراد مهمی هم در شرکت اثر  می‌گذارید. کار اصلی در هنگام شروع یک پروژه تحلیلی، این است که بطور شفاف  اهداف پایانی را تعریف کنید. پروژه هایی که تاثیر مثبت اقتصادی روی شرکت می‌گذارند، اغلب ادامه دار می‌شوند. از این رو بهترین کار این است که اهداف پروژه را با تاثیرات اقتصادی گره بزنید.منتظر قسمت های بعدی این مجموعه از دایکه باشید. تا بعد…</description>
                <category>نشریه دایکه</category>
                <author>dayche-group</author>
                <pubDate>Mon, 30 Sep 2019 15:32:41 +0330</pubDate>
            </item>
                    <item>
                <title>فیصله دادن به مبحث Logging در جاوا (قسمت اول)</title>
                <link>https://virgool.io/dayche-group-Blog/java-logging-tutorial-fchaqkhhzhsi</link>
                <description>با عرض سلام و ادب خدمت همکاران عزیز. خوشحالم که در اینجا هستید.احتمالا مجبور شدید که از فریمورک‌های لاگ انداختن استفاده کنید. توی یک محصول واقعی، لاگ جز لاینفک محصول است، و بعنوان برنامه‌نویس حتما باید از آن استفاده کنید. شاید اصلا برای رسیدن به این فریضه خودتان دست بکار شده باشید و چنین امکانی را ایجاد کرده باشید (بدون استفاده از فریمورک). شاید هم تازه گرایش پیدا کردید که از فریمورک لاگ انداختن استفاده کنید، و حسابی بین کتابخانه‌هایی که هستند سردرگم هستید! اگر به گزاره آخر بله گفتید، یعنی تازه می‌خواهید شروع کنید و بین انواع کتابخانه‌ها سردرگم هستید، این مقاله برای شماست! واقعا چه تفاوتی بین slf4j و log4j هست؟ logback چیه و کی از log4j2 استفاده کنیم؟ یا اصلا مگه خود JDK یک پکیج بنام java.util.logging ارائه نکرده؟ پس این بازی‌ها چیه؟! در این مقاله بحث لاگ را تمام خواهیم کرد و به این سردرگمی فیصله خواهیم داد.فهرستهدفتاریخچهکدام کتابخانهبعدش!هدفچرا باید از لاگ کردن استفاده کنیم؟ طبیعتا برای دیباگ کردن و پی‌بردن به وضعیت برنامه در هنگام اجرا و کشف مشکل و مانیتور کردن رفتار برنامه و کاربران. شاید دلایل دیگری هم داشته باشید، ولی من تقریبا برای محقق شدن چنین مسائلی به سراغ لاگ گرفتن از سیستم می‌روم. دلایل دیگری هم می‌تواند داشته باشد؟ صد البته! شما احتمالا هدفتون از این کار مشخص شده است که می‌خواهید این کار را انجام دهید، پس مسئله‌ی من در اینجا پرداختن به اهمیت لاگ نیست.مسئله اینجا است که شما می‌خواهید &quot;چیزی&quot; را لاگ کنید (حال به هر هدفی!). عکس را نگاه کنید. پیغامی را میخواهید به یک آبجکتی که وظیفه‌ی لاگ کردن دارد بفرستید و انتظار دارید آن آبجکت‌ هم برای شما اون پیغام را &quot;جایی&quot; ذخیره کند که بعدها شما بتوانید به آن مراجعه کنید. این کلیت فرایندی است که می‌خواهیم انجام دهیم. حالا باید به تمام اجزای آن بپردازیم و آن را باز کنیم.تاریخچههمانطور که در مقدمه اشاره شد، در JDK 1.4 یک پکیج built-in برای لاگ ارائه شد. اما واقعیت این است که این پکیج فریمورک مناسبی برای استفاده نبود، یا اجازه دهید بهتر بگویم، امکانات زیادی برای استفاده نداشت. به مرور زمان فریمورک‌های دیگری وارد گود شدند که به مراتب بهتر و بهتر بودند. این پکیج مشکلات پرفورمنسی داشت، زیاد قابل انعطاف نبود و همانطور که اشاره کردم مردم به امکانات بیشتری نیاز داشتند.این پکیج کلاسی بنام java.util.logger.Logger داشت که نقش همان آبجکت LOGGER در عکس را بازی می‌کند. در اصل این کلاس متدی بنام getLogger() دارد که بعنوان پارامتر اسم کلاس را می‌گیرد و initialize می‌شود. و خب حالا جزء بعدی، لاگ را چکار کند؟ نمایش بدهد یا در یک فایل بنویسد؟ پکیج logger اینجا مفهومی را مطرح می‌کند بنام handlers. بعبارتی در handler ما مشخص می‌کنیم که توی کنسول لاگ را نمایش دهد یا در فایل ذخیره کند. میتونید توی این لینک بیشتر درموردش بخونید. ما توی این مقاله کاری به آن نداریم.خب وقتی چنین چیزی رخ میده توی جامعه نرم‌افزار آزاد (یعنی برای یک هدف مهم، ابزار مناسبی نباشد) چه می‌شود؟ مشخص است! برنامه‌نویسان شروع می‌کنند به توسعه کتابخانه‌های بهتر. در همین حین کتابخانه‌ای بنام log4j توسعه داده شد که برای سال‌ها متمادی عالی بود و مردم به کرات از آن استفاده می‌کردند.در این کتابخانه هم مشابه همان پکیج JDK کلاسی بنام Logger هست که یک متد getLogger() دارد و دقیقا مشابه قبلی، به عنوان پارامتر اسم کلاس را می‌گیرد. در log4j بجای handlers ما appenders داریم. همان نقش را دارد کاملا. انتخاب‌های ما در کتابخانه log4j خیلی بیشتر است. در زیر آن‌ها را لیست می‌کنیم:Log4j Appenders:FileConsoleRolling file &#40;daily&#41;JDBCSMTPJMSهمانطور که مشاهده می‌کنید امکان انتقال به دیتابیس یا حتا ایمیل کردن (SMTP) هم موجود می‌باشد. جزء دیگه‌ای که از log4j می‌ماند بحث Formatting است. اینکه لاگ به چه شکل و شمایلی باشد. که بعدا در مورد اینکه لاگ به چه فرمت‌هایی می‌تواند باشد صحبت خواهیم کرد. علی‌الحساب بگذریم!خب، بنظر با log4j همه چیز عالی میاد، آیا قصه‌ی فریمورک‌های لاگ انداختن در اینجا به پایان می‌رسد؟ نه متاسفانه. اجازه دهید در مورد چالشی که پیش رو بود صحبت کنیم و بگوییم چطور آن را حل کردند.فرض کنید در کدهایتان از java.util.logging استفاده کردید، حالا می‌خواهید آن را با log4j جابجا کنید؟ چکار باید کنید؟ باید تمام کدها را تغییر دهید،‌ مصیبت بار است،‌ چرا که اصلا ماهیت لاگ هم این است که تقریبا در هر متدی وجود دارد. برای حل چنین چالشی آمدند و Facade Library تعریف کردند. ۲ کتابخانه بعنوان facade library عرضه شد:APACHE COMMONSslf4jکتابخانه sla4j به مراتب مشهورتر و پراستفاده‌تر است. اما منظور ما از کتابخانه‌های facade چیست؟ کتابخانه‌های facade فقط اینترفیس هستند و فاقد implementation هستند. بعبارتی استانداری هستند که کتابخانه‌هایی نظیر log4j آنها را پیاده‌سازی می‌کنند. چه مزیتی دارند؟ چالشی که مطرح شد را برطرف می‌کنند. بعبارتی ما در کدها طبق استاندارد sla4j کد می‌زنیم، و بواسطه‌ی log4j پیاده‌سازی می‌کنیم. به این شکل هر زمان بخواهیم log4j را با java.util.logger جابجا کنیم، بدون تغییر می‌توانیم این کار را انجام دهیم. چون شکل کد ما بر اساس sla4j می‌باشد.پس تفاوت رو تونستید قائل بشید؟ apache commons و sla4j کتابخانه‌هایی نیستند که در واقع عملیاتی انجام دهند. آنها صرفا اینترفیس هستند. ولی log4j و JDK logging کتابخانه‌هایی هستند که این استانداردها رو پیاده‌سازی کردند (بعبارتی عملیاتی هستند). خب، تمام شد قصه‌ی کتابخانه‌ها؟ نه!کتابخانه‌ی log4j دیگه توسعه داده نمی‌شود. الان کتاب‌خانه‌ی جدیدتری هست بنام log4j2 که از هر نظر عملکرد بهتری نسبت به log4j دارد. کتابخانه‌ی دیگری هم هست بنام logback. بطور کلی در این روزها ۲ کتابخانه‌ی مطرح برای لاگ وجود دارد که هر دوی آنها بر پایه‌ی sla4j api می‌باشند:log4j2logbackاما کدام؟!کدام کتابخانهاول از هر چیز، من برای کتابخانه facade از sla4j استفاده می‌کنم، خیلی محبوبیت و مقبولیت بیشتری دارد. و همه کتابخانه‌های مرسوم و محبوب از آن استفاده می‌کنند. ولی برای پیاده‌سازی چه؟پیشنهاد می‌کنم که قید استفاده از log4j را بزنید. چرا که هم توسعه‌ آن متوقف شده است و قدیمی است و هم گزینه‌های بهتر موجود است. بحث java.util.logging را هم که نمی‌کنم، با توجه به توضیحاتی که دادم این کتابخانه در انتخاب‌های من گزینه‌ی آخر است. انتخاب‌های من می‌ماند بین log4j2 و logback.کتابخانه‌ی log4j2 یک مقدار امکانات بیشتری نسبت به logback دارد، بعنوان مثال:Lazy loading messageAsync loggingاما کتابخانه‌ی logback از محبوبیت بیشتری برخوردار است و توسط همان تیمی توسعه داده می‌شود که sla4j را توسعه دادند. انتخاب من logback است. خاطرتون هست دیگه؟ شما بواسطه‌ی یک api واسط (یعنی همان sla4j) می‌توانید هر زمانی که خواستید براحتی logback را با log4j2 تعویض کنید.بعدش!و اما بعد؟ خب حال چطور استفاده کنیم؟ با من همراه باشید تا در قسمت دوم می‌خواهم کتابخانه‌ی logback را بشکافم و از آن در عمل استفاده کنم. در آن بین به مفاهیم زیادی از مبحث لاگ خواهم پرداخت.</description>
                <category>نشریه دایکه</category>
                <author>محمد عباسی</author>
                <pubDate>Wed, 07 Aug 2019 15:38:30 +0430</pubDate>
            </item>
                    <item>
                <title>مروری اجمالی به آنچه که هایبرنیت می‌کند - قسمت چهارم</title>
                <link>https://virgool.io/dayche-group-Blog/hibernate-tutorial-part-4-gaov3z6wmvd9</link>
                <description>سلام.خوشحالم که به اینجا رسیدیم. اگر کار را پس از همین‌ پست به پایان ببرم نیز از خودم راضی خواهم بود. چرا که بخش اعظمی از مبحث نگاشت را پایان داده‌ام. دوستان زیادی تلاش کرده‌اند به فارسی hibernate را توضیح دهند، اما از دید من (تاکید می‌کنم برای من) مقاله‌ای نبوده است که یکپارچه و یک تیکه به تمام ماجرا بنگرد. به همین خاطر ارزش زیادی برای این سری از مقالات قائل هستم. چون من از ابتدای کار، به کمک چندین منبع و چکیده کردن آن‌ها و ساعت‌ها مطالعه در بحث هایبرنیت توانستم برای خودم مباحث را یکپارچه کنم.اولین باری که سراغ هایبرنیت رفتم مهرماه سال ۹۶ بود، متاسفانه با حجم عظیمی از ندانم‌ها طرف بودم، و سخت‌ترین بخش برای من بحث نگاشت‌ روابط بود (Relational Mapping). امروز دقیقا به همین بحث می‌پردازیم. مطمئن باشید که در کار به شدت به این بخش وابسته خواهید بود. و در هر مصاحبه کاری که قرار باشد مهارت شما نسبت به هایبرنیت سنجیده شود دست‌کم ۲ پرسش از این بخش خواهد بود.مسئله‌ی دیگری که شاید بد نباشد با شما درمیان بگذارم،‌ علت استفاده از متن به جای ویدیو است. ویدیو یک مزیت بزرگ دارد، شما دقیقا با چند و چون پیاده‌سازی آشنا می‌شوید. گرچه من تمام کدهایی را که برای پیاده‌سازی نیاز بوده را اینجا به اشتراک گذاشته‌ام، اما عمل کردن و فهمیدن آن تلاش مضاعفی می‌خواهد که باید به گردن بگیرید. مزیت دیگر ویدیو راحتی ایجاد آن است. نوشتن به مراتب سخت‌تر است و انرژی بیشتری می‌طلبد. ویدیو را راحت‌تر می‌توانستم تهیه کنم چرا که هم به ابزار تدوین، و هم ابزار با کیفیت ضبط دسترسی داشتم. اما چرا به سراغ مقاله‌ی متنی آمدم؟ قطعا دلیلم جست‌وجوی اینترنتی و دیده شدن نبوده است. این دست آموزش‌ها در یوتیوب با اقبال بهتری روبه‌رو می‌شود. من تلاش می‌کنم تا بتوانم دفتری را بعنوان رفرنس تهیه کنم، صد البته که رفرنس کامل نخواهد بود، منظور من این است که هر گاه مطلبی را فراموش کردید بتوانید به راحتی پیدا کنید، و به سراغش بیایید، نه این که مجبور باشید چندین ویدیو را بالا پایین بکنید تا ببینید دقیقا در کدام قسمت فلان مطلب ذکر شده بود!مباحثی مثل هایبرنیت مخاطب عام ندارد،‌ تقریبا فیدبک جدی‌ای که تا کنون دریافت کرده‌ام،‌ ولی درک می‌کنم که شاید شمایی که اکنون در حال مطالعه هستید در زمانی باشید که ماها از نگارش این مقاله گذشته باشد. پس ۲ نکته را با شما درمیان می‌گذارم. من تمام تلاشم را برای نگارش دقیق مقالات بکار می‌برم، سعی می‌کنم سمبل‌‌کاری نشود، پس نگران این موضوع نباشید. نکته‌ی دوم اینکه هایبرنیت در حال پیشرفت است، همین حالا که صحبت می‌کنیم نسخه‌ی ۶ آن در شرف انتشار است. شاید بعضی از APIهایی که از آن‌ها استفاده می‌کنیم، تغییر کند، اما دوست گرانقدر، بخش اعظمی از مباحثی که تاکنون گفته شده است کاملا تئوریک هستند، دقیقا مشابه این قسمت و ۲ قسمت قبلی و ابتدای قسمت اول. این‌ها تقریبا هیچ زمانی نقض نمی‌شوند، شاید به آنها اضافه شود، ولی احتمال کاسته شدن از آن کم است، این اتفاق هم بیافتد چیزی از دست نخواهید داد.لینک قسمت‌های مرتبطقسمت اولقسمت دومقسمت سوم&lt;br/&gt;فهرستنگاشت روابط - Relational Mappingدنیای برنامه‌نویسی شی‌گرا احاطه شده از کلاس‌ها و روابط بین آنها. این روابط ساختارهایی هستند که آبجکت‌ها را بنوعی دیگر از آبجکت‌ها مرتبط می‌کند (لینک می‌کند). نکته. من در اینجا (بخشی که مربوط به جاوا است) وقتی از روابط صحبت می‌کنم منظورم چیست؟ منظورم لغت Associations است. چون relation رو هم رابطه می‌گویم (در بخشی که مربوط به دیتابیس است)، الزامی دیدم که بگویم من هر دوی این‌ها را یک چیز می‌گویم.پرسش. گیجمان نکنید، اصلا association چه چیزی بود توی دنیای برنامه‌نویسی که می‌گویید آن احاطه شده از کلاس‌ها و associationهای آنها؟!پاسخ. خواهش می‌کنم سخت نگیرید، مطمئن هستم بلد هستید. association به روابط بین چندین آبجکت اشاره می‌کنه (refers to the relationship between multiple objects). بعبارت دیگر به چگونگی ارتباط آبجکت‌ها با هم و همچنین چگونگی استفاده از قابلیت‌های یکدیگر اشاره می‌کند(refers to how objects are related to each other and how they are using each other&#x27;s functionality). در دنیای برنامه‌نویسی شی‌گرا (نه آنطور که شما میگید فقط دنیای برنامه‌نویسی) ۲ نوع رابطه‌ی مهم دارید. یک Composition و یکی Aggregation. این‌ها چه هستند را سرچ کنید!پیش از هرچیز بگویم، هر ارتباط جهت (direction) دارد. می‌تواند یک طرفه (unidirectional) یا دو طرفه (bidirectional) باشد. ارتباط یک طرفه بطور مشخص با فلش جهت آن نشان داده می‌شود:Unidirectional Associationو ارتباط دو طرفه در UML با خط ممتد مشخص می‌شود:Bidirectional Associationحتا می‌توان تعداد آبجکت‌های اشاره شده در ارتباط را نیز مشخص کرد. بعبارتی در UML چندی ارتباط یا همان کاردینالیتی آن را مشخص کرد. به تصویر زیر دقت کنید، هر ارتباطی که بین کلاس‌ها برقرار شده است (که با فلش یا خط نشان داده‌شده است) شامل ۲ عدد نیز می‌شود. بعنوان مثال ارتباط بین Platform و Decive ID را مشاهده کنید. اول از همه با توجه به فلش متوجه می‌شویم که ارتباط یک‌طرفه است، و مالک ارتباط Device ID است. و همچنین به کمک * و 1 که در ارتباط نشان داده شده، متوجه می‌شویم که یک ارتباط چندبه‌یک است. در جاوا وقتی بیشتر از یک آبجکت را می‌خواهیم از انواع مجموعه‌ای Collections، List، Set و حتا Map که همه‌ی آنها در پکیج java.util هستند، استفاده می‌کنیم.هر ارتباط نیز یک مالکیت دارد (ownership). بعبارتی کسی صاحب (owner) رابطه است. در روابط یک طرفه مالک رابطه بطور ضمنی مشخص است (در عکس اول (Unidirectional Association) مشخص است که کلاس A مالک رابطه است)، اما در ارتباط‌های دوطرفه باید بطور واضح مالکیت رابطه را مشخص کنیم. روابط در دیتابیس‌های رابطه‌ای - Relationships in Relational Databasesدر دنیای رابطه‌ای مسائل متفاوت است چرا که همه چیز این‌جا رابطه (relation) است. که به آن‌ها جدول هم می‌گوییم. به این معنا که همه چیز اینجا با جدول مدل می‌شود. برای نگاشت یک association دیگر List، Set و یا Map نداریم، در عوض جدول داریم. فلذا برای نگاشت رابطه‌ی بین یک کلاس با کلاس دیگر باید از ارجاع جدولی (table reference) استفاده کنیم. که این ارجاع به ۲ روش مختلف مدل می‌شود:استفاده از کلید خارجی (join column)استفاده از جدول میانی (join table)اجازه بدید این ۲ روش را با تصویر به شما نمایش بدم. از کتاب Beginning Java EE این تصاویر را برمی‌دارم. فرض کنید موجودیتی بنام Customer داریم که با موجودیت Address یک ارتباط یک به یک دارد. حال با استفاده از متد Join Column به این شکل می‌شود:ارتباط یک به یک با استفاده از Join Columnهمانطور که ملاحظه می‌کنید در روش اول با استفاده از کلیدخارجی (Join Column) این ارتباط نمایش داده شده است. حال همین ارتباط یک به یک را می‌توان با استفاده از جدول میانی نمایش داد. توجه داشته باشید که ارتباط یک به یک را معمولا با استفاده از کلیدخارجی مدل می‌کنند، اما در اینجا که هدف ما بحث آموزش است روش جدول میانی (Join Table) را هم نمایش می‌دهیم:ارتباط یک به یک با استفاده از Join Tableهمانطور که خدمتتون عرض کردم، از جدول میانی عموما برای مدل کردن ارتباط‌های یک‌به‌چند و یا چند‌به‌چند استفاده می‌شود.خب، نگاهی به مطالب بالا بیاندازید، چه چیزهایی را گفتیم؟ گفتیم در جاوا ارتباط‌ها جهت دارند، یا به عبارتی مالکیت در آنها مطرح است. و نشان دادیم که چندی ارتباط را در جاوا چطور پیاده سازی می‌کنیم‌ (در صورت نیاز از انواع کالکشن‌ها استفاده می‌کنیم) و نشان دادیم که در دیتابیس چگونه است. گفتیم ارتباطات در دیتابیس به ۲ شکل (یکی با کلیدخارجی و دیگری با جدول میانی) مدل می‌شود. حالا وقت آن است که برویم سراغ JPA و امکاناتی که آن برای نگاشت آبجکت‌های جاوا به جداول دیتابیس فراهم کرده نگاهی بیاندازیم. البته مشخصا منظور ما نگاشت ارتباطات است. ارتباطات بعضا پیچیده، چرا که پیش از این انواع دیگر نگاشت (بغیر از وارثت) را بررسی کردیم.ارتباطات موجودیت - Entity Relationshipsهایبرنیت یا دقیق‌تر JPA روابط را خودش آنطور که می‌فهمد بصورت پیش‌فرض برای ما نگاشت می‌کند (بدون آنکه چیزی به آن بگوییم) اما احتمالا این روش همان چیزی نباشد که مناسب کار ما باشد. به همین خاطر امکاناتی برای سفارشی‌سازی (customize) کردن عملیات نگاشت فراهم کرده است.چندی ارتباطات ممکن بین ۲ موجودیت شامل یک‌به‌یک، یک‌به‌چند، چندبه‌یک و چندبه‌چند می‌شود. به همین ترتیب برای نگاشت آن انوتیشن‌های @OneToOne، @OneToMany، @ManyToOne و @ManyToMany را فراهم کرده است.تمام این ارتباطات می‌تواند در حالت یک‌طرفه یا دوطرفه برقرار شود. (خاطرتان هست که قسمت اول در مورد مالکیت و جهت ارتباط صحبت کردیم). فلذا تمام حالاتی را که می‌تواند رخ دهد را در عکس زیر آورده‌ام:تمام ترکیبات ممکن!من به تمام این حالات می‌پردازم، اما خواهید دید که ارائه‌ی چند مثال بقیه مباحث رو تکراری می‌کنه. پس بهتر است بگویم توضیحاتی در ادامه خواهم داد که تمام این حالات را پوشش بدهد.متوجه هستید که وارد چه مباحث جذابی شده‌ایم؟ در عین سادگی جذابیت زیادی دارند. همراه باشید!یک‌طرفه (Unidirectional) و دوطرفه (Bidirectional)!همانطور که تو بخش اول هم متذکر شدیم، جهت در بحث مدل‌کردن آبجکت امری طبیعی است. در یک ارتباط یک‌طرفه، آبجکت A به آبجکت B اشاره می‌کند، در یک ارتباط دوطرفه، هر دو آبجکت بهم اشاره می‌کنند. اجازه بدهید دیگر وارد مثال شویم تا بهتر درک کنیم.در یک ارتباط یک‌طرفه، موجودیت Customer یک فیلد از نوع Address دارد (در عکس زیرین نیز مشخص است). این ارتباط یک طرفه است، از یک سمت به سمت دیگر اشاره می‌شود. بعبارت دیگر Customer مالک این ارتباط است.خب، اجازه دهید در ادبیات دیتابیس هم این موضوع را بررسی کنیم. در ادبیات دیتابیس جدول CUSTOMER کلیدخارجی‌ای (Join Column) دارد که به ADDRESS اشاره می‌کند. هر زمان هم که شما مالک ارتباط هستید، می‌توانید ارتباط را تغییر دهید. یعنی چه؟ یعنی اگر بخواهیم اسم کلیدخارجی (که به ADDRESS اشاره می‌کند) را تغییر دهیم باید موجودیت Customer را تغییر دهیم (مالک رابطه).ارتباط یک طرفههمانطور که اشاره کردیم یک ارتباط می‌تواند دوطرفه نیز باشد. در همین مثال خودمان اگر یک فیلد از نوع Customer در موجودیت Address قرار دهیم، این ارتباط را به صورت دوطرفه درآورده‌ایم.ارتباط دوطرفه بین Customer و Addressپرسش. من آشناییِ خیلی کمی با UML دارم. در ارتباط یک‌طرفه وقتی گفتید یک فیلد از Address در کلاس Customer قرار دهیم، من در دیاگرام Customer فیلد آدرس را مشاهده نکردم. و به همین ترتیب در ارتباط دوطرفه هم که فیلدی از جنس Customer در Address قرار دادیم، دوباره چیزی مشاهده نکردم! در صورتیکه مابقی فیلدها نوشته شده است (بعنوان مثال در Customer فیلدهای firstName، lastName و...)پاسخ. در دیاگرام‌های کلاس UML وقتی فیلدی با رابطه مشخص شده باشد، دیگر نوشته نمی‌شود. بعنوان مثال در ارتباط یک‌طرفه وقتی فلشی جهت‌دار از Customer به Address رفته است بیانگر فیلدی از جنس Address در کلاس Customer است، به همین خاطر دیگر آن را نمی‌نویسند.در یک ارتباط دوطرفه، چه کسی مالک رابطه است؟ چه کسی اطلاعات ستون پیوندی (کلیدخارجی یا همان join column) و یا اطلاعات جدول پیوندی (جدول میانی یا همان join table) را در خودش دارد؟درحالیکه ارتباطات یک‌طرفه تنها سمت مالک دارد، ارتباطات دوطرفه هم سمت مالک دارد هم سمت مقابل (inverse side) که با المان mappedBy در انوتیشن‌های @OneToOne، @OneToMany و ManyToMany قابل مشخص کردن است. در اصل mappedBy مشخص می‌کند که کدام خصیصه مالک رابطه است و وجودش در ارتباط‌های دوطرفه الزامی است.کمی گیج کننده است! می‌دانم. اجازه دهید یک توضیح کوچک دیگر هم بدهم. فرض کنید دو entity بنام‌های Customer و Address داریم. بین این دو انتیتی،‌ یک ارتباط یک‌به‌یک برقرار است (هر مشتری تنها یک آدرس دارد، و هر آدرس تنها متعلق به یک مشتری است). مالک رابطه کدام انتیتی است؟ Customer!ارتباط یک‌به‌یکِ دوطرفهاجازه دهید خیلی خودمانی توضیح دهم که چه رخ داده است، با انوتیشن @OneToOne مشخص کردیم که یک ارتباط یک‌به‌یک داریم، این انوتیشن‌را در دوطرف استفاده کردیم، پس یک ارتباط دوطرفه داریم. در سمت Address از المان mappedBy استفاده کردیم و با این مشخص کردیم که Address سمت مقابلِ (inverse side) مالک قرار دارد و همچنین مشخص کردیم دقیقا به چه ارتباطی، مرتبط است. با @JoinColumn هم مشخص کردیم که یک کلید خارجی می‌خواهیم به Address و نام ستون‌اش را نیز مشخص کردیم. توجه داشته باشید، مقداری که در mappedBy قرار می‌گیرد باید با نام propertyای که در سمت مالک تعریف شده است یکی باشد (چون می‌خواهد مشخص کند که بین این دو ارتباطی برقرار است). حالا شفاف شد؟ بنظرم باید شده باشد، ولی چنانچه نشده است نگران نباشد،‌ تازه می‌خواهیم وارد آب شویم و تنی به آب بزنیم!ارتباطِ یک‌طرفه‌ی یک‌به‌یک (OneToOne Unidirectional)چنین ارتباطی به چندی ۱ از یک طرف به سمت دیگر است. بیایید همان مثال مشتری و آدرس را توسعه دهیم. همچنان می‌خواهیم هر مشتری تنها یک آدرس داشته باشد اما (بنا به هر دلیلی) نمی‌خواهیم آدرس چیزی از مشتری بداند. یعنی ما از مشتری ‌می‌خواهیم به آدرس برسیم، اما از آدرس به مشتری نه! عکس زیر گویای مطلب هست، نمونه‌هایش را هم در مثال‌های قبل مشاهده کردید.اینبار چون ارتباط یک طرفه است و مالک ارتباط هم Customer می‌باشد، اطلاعات مروبط به نگاشت را فقط در انتیتی Customer قرار می‌دهیم و نیازی نیست که انتیتی آدرس چیزی از آن بداند.@Entity
public class Customer {
        @Id @GeneratedValue
        private Long id;
        private String firstName;
        private String lastName;
        private String email;
        private String phoneNumber;
        @OneToOne (fetch = FetchType.LAZY)
        @JoinColumn(name = &quot;add_fk&quot;, nullable = false)
        private Address address;
       // Constructors, getters, setters
       }به گمانم کاملا واضح است، اما باز هم برای رفع هر سوتفهامی، کد مربوط به انتیتی Address را هم قرار می‌دهم تا ملاحظه کنید که هیچ چیز آن تغییر نکرده است:@Entitypublic class Address {
        @Id @GeneratedValue
        private Long id;
        private String street1;
        private String street2;
        private String city;
        private String state;
        private String zipcode;
        private String country;
        // Constructors, getters, setters
        }همانطور که ملاحظه می‌کنید آدرس هیچ اطلاعاتی مربوط به نگاشت را ندارد.پرسش. در انتیتی Customer المانی بنام fetch اضافه کردید و مقدار آن را برابر با LAZY قرار دادید، آن چیست؟پاسخ. بله، متاسفانه هنوز به سراغ fetch کردن نرفته‌ایم، به زودی آن را توضیح خواهیم داد. اما اگر بطور خلاصه بخواهم بگویم هدف من در اینجا این بوده است که اگر من اطلاعات مشتری را خواستم نیازی نیست اطلاعات مربوط به آدرس آن هم برای من بازیابی شود مگر اینکه صراحتا بگویم! فعلا به همین توضیح مختصر بسنده کنید.ارتباط یک‌طرفه‌ی یک‌به‌چند (ManyToMany Unidirectional)خب، حال فرض کنید که ۲ انتیتی بنام‌های Order و OrderLine داریم که یک ارتباط یک‌به‌چند یک‌طرفه بین آنها برقرار است. مالک ارتباط نیز Order می‌باشد. خب، تا همینجای کار باید حدس زده باشید که چطور باید نگاشت صورت بگیرد. اگر نه، عیبی ندارد، اجازه دهید بیشتر توضیح دهم.هر Order چندین OrderLine دارد. ارتباط از سمت Order به OrderLine است (یک طرفه). فلذا OrderLine هیچ اطلاعاتی در مورد نگاشت این ارتباط ندارد. پس ما فقط باید یک آبجکت از OrderLine درون انتیتی Order قرار دهیم، درست است؟ نه کاملا! ما باید لیستی از آبجکت‌های OrderLine را درون انتیتی Order قرار دهیم (چرا که هر Order چندین OrderLine دارد و بعبارتی ارتباط یک به چند است).ارتباط یک‌به‌چندخب، کد انتیتی‌های مربوطه به شکل زیر است:Order@Entity
public class Order {
        @Id @GeneratedValue
        private Long id;
        @Temporal(TemporalType.TIMESTAMP)
        private Date creationDate;
        private List&lt;OrderLine&gt; orderLines;
        // Constructors, getters, setters
}OrderLine@Entity
@Table(name = &quot;order_line&quot;)
        public class OrderLine {
        @Id @GeneratedValue
        private Long id;
        private String item;
        private Double unitPrice;
        private Integer quantity;
        // Constructors, getters, setters
 }خوب نگاه کنید! بنظر هیچ اطلاعاتی مربوط به نگاشت یک‌به‌چند در انتیتی Order نیست! ما گفتیم هیچ انوتیشنی‌(اطلاعاتی) نباید در انتیتی OrderLine قرار داد چرا که ارتباط یک‌طرفه است. اما اینجا انوتیشنی هم در Order قرار نداده‌ایم و فقط لیستی از آبجکت‌های OrderLine را تعریف کرده‌ایم. چرا؟هایبرنیت زمانیکه ببینید یک انتیتی لیستی از یک انتیتی دیگر را در خودش دارد، بصورت خودکار متوجه می‌شود که یک ارتباط یک‌به‌چند وجود دارد. و انگار که خودش انوتیشن @OneToMany را برای فیلد مربوطه قرار می‌دهد. اما سوال دیگر، چطور در دیتابیس نگاشت می‌کند؟ بصورت پیشفرض هایبرنیت ارتباط یک‌به‌چند را با جدول میانی (@JoinTable) ایجاد می‌کند. مدل جدول‌ها با استفاده از جدول میانیمیبینید؟ جدولی میانی بنام ORDER_ORDER_LINE ایجاد کرده است و ترکیب آیدی جدول ORDER و آیدی جدول ORDER_LINE را بعنوان کلید اصلی آن قرار داده است. اسامی چطور انتخاب شده است؟ منظورم اسامی جدول ایجاد شده با اسم ۲ ستون آن است. این اسامی بصورت پیش‌فرض گذاشته شده است. چنانچه بخواهید آن‌ها را تغییر دهید، دیگر باید خودتان صراحتا وارد عمل شوید و اجازه ندهید هایبرنیت تنظیمات پیش‌فرضش را اعمال کند. پس من انتیتی Order را به شکل زیر تغییر می‌دهم:@Entity
public class Order {
        @Id @GeneratedValue
        private Long id;
        @Temporal(TemporalType.TIMESTAMP)
        private Date creationDate;
        @OneToMany
        @JoinTable(name = &quot;jnd_ord_line&quot;,
                joinColumns = @JoinColumn(name = &quot;order_fk&quot;),
                inverseJoinColumns = @JoinColumn(name = &quot;order_line_fk&quot;) )
        private List&lt;OrderLine&gt; orderLines;
        // Constructors, getters, setters
        }
کد را خوب بنگرید! قسمتی را که بولد کردم را خوب نگاه کنید، در اینجا اسم جدول میانی و همچنین اسم ستون‌های آن را اضافه کرده‌ام. با این تنظیمات همان مدل قبلی ایجاد می‌شود ولی با اسامی جدید و دلخواه من.همه چیز شفاف است؟ امیدوارم باشد. ببینید دوستان پیش‌فرض برای مدل کردن ارتباط یک‌به‌چند استفاده از جدول میانی است، اما فرض کنید بنابه‌هردلیلی من تصمیم بگیرم که از کلیدخارجی (Join Column) استفاده کنم. چکار باید کرد؟ حتما میدا‌نید که به راحتی فقط باید بجای @JoinTable که جدول میانی ایجاد می‌کند از @JoinColumn استفاده کنم. نگاه کنید که چطور دوباره کد مربوط به انتیتی Order را ریفکتور می‌کنم:@Entity
public class Order {
        @Id @GeneratedValue
        private Long id;
        @Temporal(TemporalType.TIMESTAMP)
        private Date creationDate;
        @OneToMany(fetch = FetchType.EAGER)
        @JoinColumn(name = &quot;order_fk&quot;)
        private List&lt;OrderLine&gt; orderLines;
        // Constructors, getters, setters
  }به همین راحتی. حالا مدل من به چه شکل می‌شود در دیتابیس؟ عکس زیر را نگاه کنید:مدل جدول‌ها با استفاده از کلیدخارجیخب، یک مدل نگاشت دیگر باقی می‌ماند تا بحث مربوط به آن تمام شود. متاسفانه ویرایش‌گر ویرگول بسیار سنگین شده است و نوشتن در آن سخت شده است. بعضی از عکس‌هایی هم که آپلود می‌کنم بی‌خودی و بی‌دلیل می‌پَرَد! بهتر است مطلب جدیدی را شروع کنم.ممنونم که تا اینجا همراهی کردید، و امیدوارم که این مقالات به درد شما خورده باشد!</description>
                <category>نشریه دایکه</category>
                <author>محمد عباسی</author>
                <pubDate>Wed, 29 May 2019 12:25:11 +0430</pubDate>
            </item>
                    <item>
                <title>کار با MongoDB در جاوا (اتصال +‌ CRUD) - قسمت اول</title>
                <link>https://virgool.io/dayche-group-Blog/mongodb-with-java-driver-d5jtaldyaerb</link>
                <description>کار با mongodb در جاواسلام و عرض ادب خدمت جاوا کاران عزیز.با کمترین مقدمه به سراغ نحوه‌ی اتصال به MongoDB از طریق درایور جاوا می‌روم. امیدوارم این پست مقدمه‌ای شود تا بتوانم یک‌سری از نوشته‌ها درمورد چگونگی کار با MongoDB و همچنین مباحث تئوری آن بنویسم. در حال حاضر Mongo تکنولوژی‌است که در مورد آن مطالعه می‌کنم و  به آن علاقه‌مند شدم.پیش از شروع مبحث، باید اشاره کنم که در این نوشته مفاهیم ابتدایی MongoDB را شرح نمی‌دهم. پیش‌فرض من بر این است که شما آن را نصب کرده‌اید، معانی کلماتی نظیر database، collection و document را در MongoDB می‌دانید. خیلی خوب است اگر با پوسته‌ی جاوااسکریپت آن کار هم کرده باشید.خب، شروع کنیم!پیش‌نیازهاوجود سرویس فعال MongoDB روی لوکال‌هاست با پورت پیش‌فرض ۲۷۰۱۷ (غیر از این هم بود مهم نیست، مهم وجود سرویس فعال است)درایور MongoDBنصب MongoDBنصب MongoDB به‌عهده‌ی خود شماست. بسته به نوع پلتفرمی که استفاده می‌کنید بسته‌ی موردنظر را از سایت خود Mongo دانلود کنید و نصب کنید. البته توجه داشته باشید که سایت Mongo برای ما ایرانیان عزیز بسته است و می‌بایست آی‌پی خودتان را با کمک ابزارهایی مثل VPN تغییر دهید. پس از نصب از فعال بودن سرویس آن مطمئن شوید.در ابونتو با دستور mongod می‌توانید پوسته‌ی جاوااسکریپت آن را اجرا کنید.نصب درایور MongoDB برای اتصال به آن از طریق جاواراه توصیه شده برای اضافه کردن پکیج درایور به پروژه استفاده از سیستم‌های مدیریت وابستگی نظیر Maven و Gradle است. نکته‌ی حائز اهمیت در اینجا وجود ۲ آرتیفکت متفاوت است. کدام را باید استفاده کرد؟یکی از آرتیفکت‌ها mongodb-driver است و دیگری mongo-java-driver. آرتیفکت mongodb-driver جدیدتر است و ما از آن استفاده می‌کنیم (یک اینترفیس بیشتر دارد!).&lt;dependencies&gt;  
   &lt;dependency&gt;   
         &lt;groupId&gt;org.mongodb&lt;/groupId&gt; 
         &lt;artifactId&gt;mongodb-driver&lt;/artifactId&gt;         
         &lt;version&gt;3.4.3&lt;/version&gt;
     &lt;/dependency&gt; 
&lt;/dependencies&gt; بلاک بالا وابستگی مربوط به درایور mongo را به پروژه maven اضافه می‌کند.ایجاد کانکشناز MongoClient() برای ایجاد کانکشن از یک instance فعال مونگو استفاده‌ می‌کنیم. شی MongoClinet نماینده‌ی استخری از کانکشن‌ها به دیتابیس است. به عبارت دیگر فقط به یک شی از کلاس MongoClient نیاز دارید، حتا اگر در چندین ترد مختلف می‌خواهید استفاده کنید.اتصال به یک Single MongoDB instanceخب من در اینجا چندین راه مختلف برای اتصال به دیتابیس &quot;virgool&quot; روی ماشین لوکال را نشان می‌دهم. توجه داشته باشید در همه‌ی این روش‌ها اگر دیتابیس وجود نداشته باشد، MongoDB آن را ایجاد خواهد کرد.روش ۱. مقداردهی شی MongoClient بدون هیچ پارامتری برای اتصال به اینستنس MongoDB که بصورت پیشفرض روی localhost و پورت ۲۷۰۱۷ قرار گرفته است:MongoClient mongoClient = new MongoClient();روش ۲. می‌توان hostname را مشخص کرد. بطور مثال زمانی که اینستنس MongoDB روی ماشین محلی قرار ندارد. اما همچنان پورت بصورت پیش‌فرض ۲۷۰۱۷ می‌باشد:MongoClient mongoClient = new MongoClient( &quot;localhost&quot; );روش ۳. مشخص کردن hostname و همچنین port بصورت شفاف:MongoClient mongoClient = new MongoClient( &quot;localhost&quot; , 27017 );روش ۴. شما همچنین می‌توانید از MongoClinetURI برای ایجاد connection string استفاده کنید: MongoClientURI connectionString = new MongoClientURI(&quot;mongodb://localhost:27017&quot;);
 MongoClient mongoClient = new MongoClient(connectionString);اجازه دهید کمی این بخش را بیشتر باز کنیم.شمای استاندارد برای کانکشن‌استرینگ به فرم زیر است:mongodb://[username:password@]host1[:port1][,...hostN[:portN]]][/[database][?options]]که در آن mongodb:// مشخص می‌کند که این رشته از نوع استاندارد اتصال به دیتابیس است.و username:password@ بیانگر نام‌کاربری و رمزعبور است (اگر نیاز بود) و توجه داشته باشید چنانچه در نام‌کاربری و رمزعبور کارکترهایی نظیر @، : و امثالهم دارید، باید‌ آن‌ها را به کمک  percent encoding بنویسید. سپس host[:port] را مشخص می‌‌کنید که در مثال ما localhost (یا همان 127.0.0.1) و پورت 27017 می‌باشد. و در نهایت دیتابیس را باید مشخص کرد. مشخص کردن دیتابیس اختیاری است، چنانچه نام‌کاربری‌ای که با آن لاگین می‌کنید مختص به یک دیتابیس خاص است، می‌بایست حتما آن دیتابیس را مشخص کرد. و اما بخش options! می‌توان خصوصیاتی را به کانکشن نسبت داد، چه خصوصیاتی؟  Connection String Options را ببینید!یک مثال از کانکشن‌استرینگ:mongodb://myDBReader:D1fficultP%40ssw0rd@mongodb0.example.com:27017/adminاتصال به دیتابیسهنگامی که شی MongoClinet به دیتابیس MongoDB متصل شد، می‌توان به کمک متد MongoClinet.getDatabase() به یک دیتابیس مشخص متصل شد. باید نام آن دیتابیس را در متد getDatabase مشخص کرد، چنانچه وجود هم نداشته باشد خود Mongo آن را ایجاد خواهد کرد (در زمان ذخیره اولین دیتا).مثال زیر نحوه اتصال به دیتابیس &quot;virgool&quot; را نشان ‌می‌دهد:MongoDatabase database = mongoClient.getDatabase(&quot;virgool&quot;);نکته: شی MongoDatabase بصورت immutable است!دسترسی به کالکشنخب، حالا که شی‌ای از MongoDatabase داریم، برای دسترسی به یک کالکشن خاص از متد getCollection() استفاده می‌کنیم. باید نام آن کالکشن را در متد مشخص کرد، اگر وجود نداشته باشد نیز Mongo آن را ایجاد خواهد کرد (در زمان ذخیره اولین دیتا).برای مثال، من می‌خواهم به کمک شی database به کالکشن posts در دیتابیس virgool دسترسی داشته باشم:MongoCollection&lt;Document&gt; collection = database.getCollection(&quot;posts&quot;);شی MongoCollection نیز immutable است.ایجاد یک Documentبرای ایجاد یک داکیومنت از کلاس Document استفاده می‌کنیم،‌ برای مثال JSON زیر را در نظر بگیرید:{    
    &quot;name&quot; : &quot;MongoDB&quot;,   
    &quot;type&quot; : &quot;database&quot;,    
    &quot;count&quot; : 1,    
    &quot;versions&quot;: [ &quot;v3.2&quot;, &quot;v3.0&quot;, &quot;v2.6&quot; ],    
    &quot;info&quot; : 
        { 
            x : 203, 
            y : 102 
        }   
}برای ایجاد یک داکیومنت با استفاده از Java driver باید یک شی از کلاس Doucument را با field و value مقداردهی کرد. همچنین می‌توان به کمک متد append() فیلدها و مقادیر بیشتری را به یک شی داکیومنت نسبت داد. حتا مقدار (value) می‌تواند یک شی Document دیگر باشد (برای اسنادی تو در تو). به مثال زیر توجه کنید که چگونه سند JSON بالا را تبدیل به یک شی از کلاس Document می‌کنیم:Document doc = new Document(&quot;name&quot;, &quot;MongoDB&quot;)                 
                .append(&quot;type&quot;, &quot;database&quot;)                 
                .append(&quot;count&quot;, 1)                 
                .append(&quot;versions&quot;, Arrays.asList(&quot;v3.2&quot;, &quot;v3.0&quot;, &quot;v2.6&quot;))                 
                .append(&quot;info&quot;, new Document(&quot;x&quot;, 203).append(&quot;y&quot;, 102)
                );درج یک داکیومنتحال که یک شی از کلاس MongoCollection داریم، می‌توانیم به کمک آن داکیومنت‌هایی که ایجاد کردیم را در یک کالکشن مشخص insert کنیم. برای این‌کار از متد insertOne() استفاده خواهیم کرد. توجه کنید:collection.insertOne(doc);نکته: چنانچه فیلد _id را در سند مشخص نکرده باشیم، MongoDB بصورت خودکار آن را در سند ما قرار می‌دهد!حال چگونه لیستی از داکیومنت‌ها را درج کنیم؟ ابتدا بیاید آن را ایجاد کنیم سپس با کمک متد insertMany() از کلاس MongoCollection آن‌ها را درج کنیم.برای ایجاد لیستی داکیومنت‌ها یک حلقه‌ی for ایجاد می‌کنیم تا ۱۰۰ شی امتحانی ایجاد کنیم:List&lt;Document&gt; documents = new ArrayList&lt;Document&gt;(); 
        for (int i = 0; i &lt; 100; i++) {     
                documents.add(new Document(&quot;i&quot;, i)); 
}سپس با کمک متد insertMany() شی documents را وارد کالکشن مربوطه می‌کنیم:collection.insertMany(documents);شمارش تعداد اسناد در یک کالکشنبرای شمارش تعداد اسناد در یک کالکشن از متد count استفاده می‌کنیم. انتظار داریم خط زیرین عدد ۱۰۱ را چاپ کند (۱۰۰ شی را با متد insertMany و یک شی را با insertOne درج کردیم):System.out.println(collection.count());بازیابی اسنادبرای کوئری زدن به یک کالکشن، می‌توانیم از متد find() استفاده کنیم. اگر بدون هیچ آرگومانی فراخوانی شود، تمام اسناد یک کالکشن را درخواست می‌کند و اگر آرگومانی به آن بدهیم می‌توانیم اسناد را بر اساس آن فیلتر کنیم. اگر گیج کننده شده است عذرخواهی می‌کنم، به مثال‌ها توجه کنید، گویای مطلب است.متد find() یک شی از نوع FindIterable ایجاد می‌کند که می‌توان متدهای دیگری را بصورت آبشاری (زنجیری) در آن فراخوانی کرد.پیدا کردن یک داکیومنت در کالکشنبرای بازیابی اولین سند در کالکشن از متد find بدون هیچ آرگومانی استفاده می‌کنیم که بعد از آن بصورت آبشاری متد first() را فراخوانی می‌کنیم.نکته: اگر کالکشن خالی باشد، null برخواهد گشت!Document myDoc = collection.find().first();
System.out.println(myDoc.toJson());بازیابی تمامی داکیومنت‌های یک کالکشنبرای بازیابی تمام داکیومنت‌های یک کالکشن‌ هم از متد find() بدون هیچ پارامتری استفاده می‌کنیم. بمنظور اینکه بتوانیم نتیجه را پیمایش کنیم باید متد iterator() را به متد find() زنجیر کنیم.مثال زیر تمام داکیومنت‌های یک کالکشن را برمی‌گرداند و آن‌ها را در کنسول چاپ می‌کند (۱۰۱ داکیومنت):MongoCursor&lt;Document&gt; cursor = collection.find().iterator(); 
    try {     
        while (cursor.hasNext()) {         
            System.out.println(cursor.next().toJson());     
        } 
    } finally {     
        cursor.close(); 
    }فیلتر کردن خروجیبرای درخواست داکیومنت‌هایی که با شروط مشخصی هماهنگ هستند (بعبارتی match هستند)، آبجکت فیلتر را به متد find() پاس می‌دهیم. برای راحتی ایجاد آبجکت‌های فیلتر، Java driver کلاس کمکمی‌ای بنام Filters ایجاد کرده است.برای مثال، برای یافتن اولین سندی که فیلد i آن مقدار 71 را داشته باشد، فیلتر &quot;eq&quot; را برای مشخص کردن شرط برابری به متد find() پاس می‌دهیم:myDoc = collection.find(eq(&quot;i&quot;, 71)).first();
System.out.println(myDoc.toJson());مثال زیر، تمام داکیومنت‌هایی که مقدار i آنها بزرگتر از ۵۰ هست (&quot;i&quot; &gt; 50) را برمی‌گرداند:Block&lt;Document&gt; printBlock = new Block&lt;Document&gt;() {
     @Override
     public voidapply(final Document document) {
         System.out.println(document.toJson());
     }
};

collection.find(gt(&quot;i&quot;, 50)).forEach(printBlock);برای مشخص کردن یک بازه نظیر i بزرگتر از ۵۰ و کوچک‌تر و مساوی ۱۰۰ باشد (50 &lt; i &lt;= 100) می‌توانید از کمکی and استفاده کرد:collection.find(and(gt(&quot;i&quot;, 50), lte(&quot;i&quot;, 100))).forEach(printBlock);آپدیت کردن داکیومنتبرای بروز کردن (آپدیت) اسنادِ کالکشن از متدهای updateOne و updateMany استفاده می‌کنیم.چیزهایی که به متدها ارسال می‌کنیم:(اول) آبجکت فیلتر، داکیومنت یا داکیومنت‌ها را برای آپدیت مشخص می‌کند. برای راحتی ایجاد آبجکت فیلتر هم Java driver یک کلاس هلپر (کمکی) بنام Filters ایجاد کرده است. برای مشخص کردن یک فیلتر خالی نیز (بعبارتی تمام داکیومنت‌های یک کالکشن را می‌خواهید)، از آبجکت خالی Document استفاده کنید.(دوم) سند آپدیتی که تغییرات را مشخص می‌کند، برای اینکه لیست عملیات‌های ممکن رو ببینید رو این کلیک کنید. این لیست را من در زیر هم خلاصه میاورم:$currentDateSets the value of a field to current date, either as a Date or a Timestamp.$incIncrements the value of the field by the specified amount.$minOnly updates the field if the specified value is less than the existing field value.$maxOnly updates the field if the specified value is greater than the existing field value.$mulMultiplies the value of the field by the specified amount.$renameRenames a field.$setSets the value of a field in a document.$setOnInsertSets the value of a field if an update results in an insert of a document. Has no effect on update operations that modify existing documents.$unsetRemoves the specified field from a document.متدهای update یک UpdateResult برمی‌گردانند که شامل اطلاعاتی درمورد تعداد داکیومنت‌های تغییر یافته است. چنانچه می‌خواهید تنها یک داکیومنت را تغییر دهید از updateOne استفاده کنید.مثال زیر، اولین داکیومنتی که شرط فیلتر را ارضا کند‌ (i مساوی با ۱۰) تغییر می‌دهد (مقدار i را برابر با ۱۱۰ قرار می‌دهد): collection.updateOne(eq(&quot;i&quot;, 10), new Document(&quot;$set&quot;, new Document(&quot;i&quot;, 110)));اما برای آپدیت کردن تمام اسنادی که با فیلتر همخوانی دارند (match) از متد updateMany استفاده خواهیم کرد.در مثال زیر مقادیر i تمام اسنادی که مقدار i آنها کمتر از ۱۰۰ می‌باشد را ۱۰۰تا افزایش می‌دهیم:UpdateResult updateResult = collection.updateMany(lt(&quot;i&quot;, 100), inc(&quot;i&quot;, 100));
System.out.println(updateResult.getModifiedCount());حذف کردن داکیومنتبرای حذف کردن اسناد از یک کالکشن می‌توانید از متدهای deleteOne و deleteMany استفاده کنید.مشابه آپدیت، برای این متدها ابتدا باید آبجکت فیلتر را پاس داد تا مشخص شود کدام سند یا سندها باید حذف شوند. که می‌توان از کلاس کمکی درایور جاوا (Filters) کمک گرفت. مشابه آپدیت، برای حذف تمام داکیومنت‌ها یک آبجکت خالی Document ارسال کنید تا بعنوان بدون فیلتر درنظر گرفته شود.متدهای حذف هم یک DeleteResult برمی‌گردانند که شامل اطلاعاتی در مورد تعداد اسناد حذف شده است.برای حذف اولین سندی که مطابق فیلتر است از متد deleteOne استفاده می‌کنیم. مثال زیر سندی را که مقدار i آن برابر با ۱۱۰ می‌باشد را حذف می‌کند:collection.deleteOne(eq(&quot;i&quot;, 110));برای حذف چندین سند هم از deleteMany استفاده می‌کنیم. مثال زیر تمام اسنادی را که مقدار آن‌ها بزرگ‌تر و مساوی ۱۰۰ می‌باشد را حذف می‌کند:DeleteResult deleteResult = collection.deleteMany(gte(&quot;i&quot;, 100));
System.out.println(deleteResult.getDeletedCount());
ساخت ایندکسبرای ایجاد ایندکس روی یک فیلد یا چندین فیلد، سند مشخص ایندکس را باید به متد createIndex() پاس داد. سند مشخص ایندکس شامل فیلدهایی که باید ایندکس شوند و همچنین نوع ایندکس هر فیلد می‌باشد، فرمت زیر را نگاه کنید:new Document(&lt;field1&gt;, &lt;type1&gt;).append(&lt;field2&gt;, &lt;type2&gt;) ...برای نوع ایندکس افزایشی، مقدار 1 را برای &lt;type&gt; قرار دهید.برای نوع ایندکس کاهشی، مقدار -1 را برای &lt;type&gt; قرار دهید.بعنوان مثال یک ایندکس افزایشی برای فیلد i ایجاد می‌کنیم:collection.createIndex(new Document(&quot;i&quot;, 1));برای دیدن تمام انواع ایندکس‌ها صفحه ایجاد ایندکس‌ها را مشاهده کنید.خب، به پایان رسید این قصه، اما حکایت همچنان باقیست. بحث مربوط به درایور جاوا برای MongoDB ادامه دارد. می‌توان خیلی بیشتر آن را بسط داد، شما بگویید، قسمت دوم آن را اضافه کنم؟</description>
                <category>نشریه دایکه</category>
                <author>محمد عباسی</author>
                <pubDate>Sat, 25 May 2019 14:20:04 +0430</pubDate>
            </item>
                    <item>
                <title>مروری اجمالی به آنچه که هایبرنیت می‌کند - قسمت سوم</title>
                <link>https://virgool.io/dayche-group-Blog/hibernate-tutorial-part-3-lu8lttggmewa</link>
                <description>سلام!به قسمت سوم مقاله‌ی &quot;مروری اجمالی بر هایبرنیت&quot; خوش‌آمدید. در این مقاله بدون مقدمه به ادامه‌ی مبحث قبل برخواهیم گشت. همراه باشید!خب، در مقاله‌ی قسمت دوم توضیح Annotationهای پایه‌ای را شروع کرده بودیم. ادامه می‌دهیم. البته ذکر یک نکته بنظرم با اهمیت است. هرچه جلوتر برویم، توضیح من در مورد انوتیشن‌های مشخص مختصرتر خواهد شد. انوتیشن‌های مشخص چه انوتیشنی است؟ آنهایی که وظیفه‌اشان مشخص است، پیاده‌سازی آنها توسط خود شما براحتی صورت می‌پذیرد، فلذا لزومی نمی‌بینم که بابت هرکدام از آنها یک پیاده‌سازی ارائه دهم.پرسش. منظور شما از انوتیشن‌های پایه‌ای چیست؟پاسخ. این فقط یک اصطلاح من است، دقت شما ستودنی است. من بطور قراردادی با خودم، انوتیشن‌هایی که مربوط به نگاشت Entity می‌شود را پایه‌ای نامیدم. چیزهایی که حتما بکار می‌آیند.لینک قسمت‌های مرتبطقسمت اولقسمت دومفهرستتوضیح Annotationهای پایه‌ای بخش ۲عملیات CRUD در هایبرنیتتوضیح Annotationهای پایه‌ای بخش ۲خب، پس از توضیح بخشی از انونیشن‌ها، حال نوبت به ادامه‌ی روند است.@Basicاین انوتیشن خصیصه‌ای بسیار مهم دارد. این انوتیشن خصیصه‌ای بنام fetch دارد که مشخص می‌کند که فیلد مدنظر به چه شکل باید بازیابی شود. این خصیصه (fetch) دو مقدار مشخص می‌تواند بگیرد. یک مقدار Lazy و دیگری Eager. بسته به نوع استفاده می‌توانید مشخص کنید که از کدام fetch type باید استفاده شود. به مثال زیر توجه کنید:@Basic(fetch = FetchType.LAZY)
@Lob
private byte[] wav;انوتیشن @Lob چیست؟! انوتیشن @Lob دقیقا برابر با نوع داده blob در دیتابیس است. وقتی فایل‌های حجیم باینری در دیتابیس داشته باشیم، از این نوع داده استفاده می‌کنیم. در اینجا هم مشخص شده است که فیلد wav از نوع داده‌ی باینری است (blob).نکته‌ی مهم این است که اگر خصیصه‌ی fetch صراحتا مشخص نشود به صورت پیش‌فرض روی Eager خواهد بود.پرسش. کاملا گیج شده‌ام! نه چیزی در مورد fetch type فهمیدم! نه چیزی در مورد @Lob!اصلا LAZY و EAGER چه فرقی باهم دارند؟ یا blob چیست؟پاسخ. حق دارید، متوجه بودم که احتمالا چنین حسی پیدا می‌کنید. اجازه دهید به ۲ سوال شما جداگانه پاسخ دهم.در رابطه با fetch type باید بگویم که این مبحثی جداگانه است و در برنامه‌ی پیش رو داریم. مهم برای من در اینجا این بود که بگویم در انوتیشن Basic می‌توانید نوع fetch type را مشخص کنید. اما اینکه دقیقا fetch type چیست و اینکه Lazy چیست یا Eager چیست، مدنظرم نبوده است. در این مورد در بزودی صحبت خواهیم کرد. کمی صبر کنید.اما در رابطه با نوع داده‌ی blob. این را اگر نمی‌دانید گوگل کنید، خارج از بحث ماست، و کاملا مربوط به دیتابیس است. ولی بطور کلی ما وقتی می‌خواهیم داده‌های باینری را ذخیره کنیم از این نوع داده استفاده می‌کنیم‌ (مثل عکس، فیلم، موزیک و...).@Columnاین انوتیشن را دیده‌اید. جدید نیست. از آن استفاده هم کرده‌اید. بیاد دارید که استفاده از خصیصه‌ی name در انوتیشن Column، اسم ستون را مشخص کردید؟ قسمت اول و دوم را نگاه کنید. خب اکنون می‌خواهیم این انوتیشن را باز کنیم و نشان دهیم چه اطلاعات دقیق‌تری میتوانیم برای ستون‌هایمان درنظر بگیریم.اجازه دهید نگاهی به کد خود این انوتیشن بیاندازیم:@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface Column {
    String name() default &quot;&quot;;
    boolean unique() default false;  // خط چهارم
    boolean nullable() default true;
    boolean insertable() default true;
    boolean updatable() default true;
    String columnDefinition() default &quot;&quot;;
    String table() default &quot;&quot;;
    int length() default 255;
    int precision() default 0; // decimal precision
    int scale() default 0; // decimal scale
}این کد خود انوتیشن @Column است، همانطور که ملاحظه می‌کنید تمام خصیصه‌ها بعلاوه‌ی مقدار پیش‌فرض آنها لیست شده است. بعنوان مثال در خط چهارم، به خصیصه‌ی unique اشاره شده است که مقدار پیش‌فرض آن هم false است. این خصیصه مشخص می‌کند که یک فیلد (یا همان ستون در دیتابیس) باید یکتا باشد یا می‌تواند مقدار تکراری بگیرد.همانطور که متوجه شده‌اید، به کمک این انوتیشن و خصیصه‌هایش میتوانید محدودیت‌های بسیاری را برای یک فیلد درنظر بگیرید. از مهم‌ترین خصیصه‌هایی که می‌توان به آن اشاره کرد مقادیر unique، nullable، length و name می‌باشد. اگر خاطرتان باشد در قسمت دوم از خصیصه‌ی table هم استفاده کردیم (جایی که می‌خواستیم یک Entity را به چندین جدول تقسیم کنیم).به مثال زیر دقت کنید:@Entity
public class Book {
    @Id @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    @Column(name = &quot;book_title&quot;, nullable = false, updatable = false)
    private String title;
    private Float price;
    @Column(length = 2000)
    private String description;
    private String isbn;
    @Column(name = &quot;nb_of_page&quot;, nullable = false)
    private Integer nbOfPage;
    // متد های گتر و ستر و سازنده
}@Temporalاین انوتیشن برای مشخص کردن تاریخ استفاده می‌شود. مثال زیر گویای مطلب است:@Temporal(TemporalType.DATE)
private Date dateOfBirth;@Transientکلیدواژه‌ی transient در جاوا را بیاد دارید؟ که اجازه نمی‌داد یک فیلد مشخص serial شود؟ خاطرتان نیست؟ عیبی ندارد، بطور کلی فراموش کنید این جمله را. این انوتیشین وقتی برای فیلدی استفاده شود، مانع از آن می‌شود که آن فیلد مشخص نگاشت شود.بطور کلی ما به ازای هر فیلد در جاوا، یک ستون در جدول خواهیم داشت، ولی اگر این انوتیشن را برای فیلدی استفاده کنیم، مانع از آن می‌شویم که ستونی برای آن در دیتابیس لحاظ شود. شاید ما در جاوا به فیلدهایی نیاز داشته باشیم، که وجود ستونی برای آنها الزامی نباشد، با استفاده از @Transient به این هدف دست می‌یابیم!@Enumeratedبرای نگاشت کلاس‌های enum استفاده می‌شود.توضیح بیشتر از این خط را در گوگل جست‌وجو کنید!کالشکنی (مجموعه‌ای) از انواع ساده خب تقریبا داریم به جاهای قشنگ هایبرنیت می‌رسیم. مطمئن هستم تا اینجای کار کلی برایتان سوال پیش آمده که چطور ارتباطات بین Entityها را برقرار کنیم؟ چطور لیستی (مثلا از تلفن) را نگاشت کنیم؟ همه و همه را خواهم گفت. حوصله کنید و همراه باشید!در اینجا می‌خواهیم به این موضوع اشاره کنیم که اگر بخواهیم لیستی از از انواع ساده را مدیریت کنیم چه باید بکنیم. اول توضیح دهیم که منظورمان از انواع ساده چیست. مقصود از انواع ساده، کلاس‌هایی هستند که Entity نیستند. مثلا لیستی از Stringها، لیستی از Integerها و امثالهم. این‌ها را اگر بخواهیم مدیریت کنیم از ۲ انوتیشن استفاده می‌کنیم.اونتیشن @ElementCollection مشخص می‌کند که این فیلد، شامل لیستی از انواع ساده است (یعنی Stringها و یا هر چیز دیگری که Entity نیست). در کنار این انوتیشن باید از انوتیشن دیگری نیز استفاده کنیم. یعنی انوتیشن @CollectionTable که با استفاده از آن می‌توانیم اطلاعات جدول مربوطه‌اش را مدیریت کنیم. ببینید، وقتی ما مثلا لیستی از Stringها را داشته باشیم، منطقا هایبرنیت باید جدولی مجزا برای آن درنظر بگیرید که به کمک کلیدخارجی با Entity ما ارتباط دارد. حال این جدول چه مشخصاتی باید داشته باشد؟ بطور مثال چه نامی باید داشته باشد؟ این‌ها را با استفاده از @CollectionTable مشخص می‌کنیم.پرسش. منظور شما از لیست چیست؟ منظورتان کلاس List یا پیاده‌سازی آن مثل ArrayList است؟پاسخ. منظور من مجموعه‌ای از داده‌ها است. یعنی هم می‌تواند ArrayList باشد هم HashSet و یا HashMap و یا هر Collection دیگری. لیست منظورم دقیقا یعنی مجموعه‌ای از انواع ساده.پرسش. کلیدخارجی چیست؟ منظورم آنجایی است که گفتید هایبرنیت یک جدول جدا در نظر می‌گیرد و به کمک کلیدخارجی به جدول اصلی ارتباط می‌دهد.پاسخ. کلیدخارجی هم مشابه مبحث blob کاملا مربوط به بحث دیتابیس است. یادگیری آن هم به عهده‌ی خود شماست. انتظار من بر این بود که کلیدخارجی را بشناسید، حال که اینطور نیست عیبی ندارد. همین‌جا صبر کنید، و اول کلیدخارجی را جست‌وجو کنید و یادبگیرید، بعد ادامه دهید.خب بیایید فرض کنیم می‌خواهیم در کلاس دانشجو (Student) یک لیستی از موضوعات مورد علاقه‌ی دانشجو داشته باشیم! فرضی است کاملا! بر نوع مثال خرده نگیرید. باید چکار کنیم؟ با توجه به توضیحاتی که دادیم باید ساده باشد. یک ArrayList به موجودیت (Entity) دانشجو اضافه می‌کنیم.نکته‌ی بسیارمهم: وقت آن است که با دقت تمام خط به خط کدها را نگاه کنید و ملاحظه کنید که دقیقا چه اتفاقی افتاده است. من تمام خروجی‌ها بعلاوه‌ی کدها را می‌گذارم. فقط با تفسیر خط به خط و نوشتن خودتان می‌توانید مطمئن شوید که فرا گرفتید. غیر از این احتمالا چیزی دستگیرتان نشود.کلاس Student:package entities;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

@Entity
public class Student {
    @EmbeddedId
    private StudentKey studentKey;
    @Column(name = &quot;sname&quot;)
    private String name;
    @Column(name = &quot;stell&quot;)
    private String tell;
    private String address;

    @ElementCollection(fetch = FetchType.EAGER)  /// از این جا به بعد خوب دقت کنید
    @CollectionTable(name = &quot;alaghemandiha&quot;)
    @Column(name = &quot;value&quot;)
    private List&lt;String&gt; favorites = new ArrayList&lt;String&gt;();

    public Student(StudentKey studentKey, String name, String tell, String address) {
        this.studentKey = studentKey;
        this.name = name;
        this.tell = tell;
        this.address = address;
    }
    public List&lt;String&gt; getFavorites() {
        return favorites;
    }
    public void setFavorites(List&lt;String&gt; favorites) {
        this.favorites = favorites;
    }
    public StudentKey getStudentKey() {
        return studentKey;
    }
    public void setStudentKey(StudentKey studentKey) {
        this.studentKey = studentKey;
    }
    public Student() {} // non-arg constructor
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getTell() {
        return tell;
    }
    public void setTell(String tell) {
        this.tell = tell;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
}کلاس Test:import entities.Student;
import entities.StudentKey;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class Test {
    public static void main(String[] args) {
        StudentKey studentKey = new StudentKey(12345,67890);
        Student student = new Student(studentKey,&quot;Mohamad&quot;, &quot;09121112233&quot;, &quot;Tehran&quot;);
        student.getFavorites().add(&quot;Book&quot;);
        student.getFavorites().add(&quot;Programming&quot;);
        student.getFavorites().add(&quot;Dancing&quot;);

        SessionFactory sessionFactory = new Configuration().configure(&quot;hibernate.cfg.xml&quot;)
                .addAnnotatedClass(Student.class)
                .buildSessionFactory();

        Session session = sessionFactory.getCurrentSession();

        session.beginTransaction();

        session.save(student);

        session.getTransaction().commit();

        session.close();
        sessionFactory.close();
    }
}خروجی مربوط به جداول:خروجی مربوط به پایگاه داده پرسش. ببینید تا اینجای کار متوجه شدم که چطور ذخیره سازی میکنید، اما اینکه همین‌ها رو چطور باید بازیابی کنم برایم سوال است! چطور باید بعنوان مثال اطلاعات یک دانشجو، بهمراه تمام علاقه‌مندی‌هایش را داشته باشم؟پاسخ. متوجه نگرانی شما هستم، اجازه دهید این موضوع را موکول کنیم به زمانی که می‌خواهیم راجع به بحث CRUD توضیح دهیم. آنجا بازیابی اطلاعات بحث خواهد شد، دوباره در بخش HQL به آن خواهیم پرداخت، باز هم در مبحث Criteria به آن برخواهیم گشت. پس نگران نباشید. توصیه‌ی قبلی من را بیاد دارید؟ به آن چیزی که نمیدانید تمرکز نکنید، به آنهایی که میدانید تمرکز کنید. همراه باشید!پرسش. متوجه شدم که چطور یک ArrayList را باید به عنوان یک جدول در نظر گرفت و یک نام هم حتا برای ستون آن گذاشتیم ()، اما چطور یک HashMap را نگاشت کنیم؟ مگر به ۲ ستون نیاز نداریم؟پاسخ. صحیح است. برای این منظور باید چنین کرد:@ElementCollection
@CollectionTable(name=&quot;track&quot;)
@MapKeyColumn (name = &quot;position&quot;)
@Column(name = &quot;title&quot;)
private Map&lt;Integer, String&gt; tracks = new HashMap&lt;&gt;();چطور یک آبجکت را Embedd کنیم؟بیاد دارید چطور کلید مرکب ساختیم؟ از همان تکنیک می‌توانیم برای Embed کردن یک آبجکت درون یک کلاس استفاده کنیم. اگر خوب بیاد ندارید ابتدا قسمت کلید مرکب را مجددا مطالعه کنید، و بعد به کد‌های پایین نگاه کنید.دقت کنید که تمام فیلدهای آبجکت Embed شده تبدیل به ستون در موجودیت مربوطه می‌شود.کلاس Address:package entities;
import javax.persistence.Embeddable;
@Embeddable
public class Address {
    private String country;
    private String city;
    private String street;
    public Address() {}
    public Address(String country, String city, String street) {
        this.country = country;
        this.city = city;
        this.street = street;
    }
    public String getCountry() {
        return country;
    }
    public void setCountry(String country) {
        this.country = country;
    }
    public String getCity() {
        return city;
    }
    public void setCity(String city) {
        this.city = city;
    }
    public String getStreet() {
        return street;
    }
    public void setStreet(String street) {
        this.street = street;
    }
}تکه کد مربوطه به Address در کلاس Student:@Embedded
private Address address;خب دوستان عزیز، حرف بیشتری راجع به نگاشت یک Entity ندارم، اگر حالتی هست که پوشش داده نشده شما متذکر شوید. چیز دیگری که مانده بحث نگاشت روابط است. روابط یک‌به‌یک، یک‌به‌چند، چندبه‌یک و چندبه‌چند و بحث مربوط به وراثت.می‌خواهم ابتدا در مورد عملیات CRUD با هایبرنیت صحبت کنم، بعد به Relation Mapping بپردازیم.عملیات CRUD در هایبرنیتهمانطور که احتمالا می‌دانید، CRUD مخفف Create، Read، Update و Delete است. این چهارگانه، عمده‌ی عملیاتی است که ما با دیتابیس انجام می‌دهیم. فلذا در ادامه می‌خواهیم به این چهار عملیات اصلی بپردازیم. حدس من بر این است که شما این چهار عمل را با خود SQL انجام داده‌اید، و حتا از طریق jdbc تجربه‌ی آن را دارید. حالا فرصت مناسبی است که این چهار عملیات را با هایبرنیت بررسی نماییم.نحوه‌ی درج (insert)خب تا اینجای کار نحوه‌ی Insert کردن به دیتابیس را مشاهده کرده‌اید. ما برای insert از متد save در کلاس Session استفاده کردیم. بیایید مرور کنیم...قبلا نیز اشاره کردم، برای انجام عملیات با دیتابیس ما نیاز به یک تراکنش داریم (اگر مفصل می‌خواهید بدانید، انتهای قسمت اول، و ابتدای قسمت دوم را مطالعه کنید). در داخل یک تراکنش است که ما با دیتابیس صحبت می‌کنیم. در تمام مثال‌ها نیز در داخل یک تراکنش متد save را فراخوانی کردیم.تاکید می‌کنم، برای عملیات insert بکمک هایبرنیت، از متد save در کلاس Session استفاده می‌کنیم:session.beginTransaction();          
session.save(object);          // آبجکتی را که میخواهیم پرسیست کنیم 
session.getTransaction().commit();نحوه‌ی بازیابی (retrieve)خاطرتان هست که گفتیم هر Entity باید یک کلیداصلی داشته باشد که با انوتیشن @Id نشانش می‌دادیم؟ فلسفه‌ی کلید اصلی چیست؟ اینکه با کمک آن به رکوردی یکتا برسیم. خب، منطقا در هایبرنیت هم برای بازیابی به کلیداصلی احتیاج داریم.برای بازیابی اطلاعات، ما از متد get در کلاس Session استفاده می‌نماییم. اما پارامترهای این متد چیست؟این متد دریکی از شکل‌های خود که ما استفاده می‌کنیم، ۲  پارامتر بعنوان آرگومان ورودی دریافت می‌کند. آرگومان اول نام کلاسی (entity) است که ما می‌خواهیم یک رکورد از آن را بازیابی کنیم. آرگومان دوم کلید آن رکورد است.فرض کنید در جدول Student، دانشجویی داریم که کلید آن 2231 است. برای بازیابی تمام رکورد آن (در قالب یک آبجکت) چنین رفتار میکنیم:ابتدا یک آبجکت از نوع دانشجو می‌سازیم، و سپس خروجی متد get را به آن پاس می‌دهیم.Student student = new Student();
session.beginTransaction();
student = session.get(Student.class, 2231);
session.getTransaction().commit();حال تمام اطلاعات مربوط به دانشجو درون آن آبجکت قرار دارد. به همین راحتی می‌توانیم از جدول اطلاعات را بارکشی کنیم.پرسش. تا اینجا بسیار ساده بود، اما صبر کنید، در آخرین مثالی که برای ما زدید برای کلاس دانشجو یک کلید مرکب ساختید، بعبارتی یک کلاس دیگر بنام StudentKey ایجاد کردید، و ترکیب شماره‌ملی و شماره‌شناسنامه آن را بعنوان کلیداصلی دانشجو قرار دادید، در این حالت چطور باید کلید را مشخص کرد؟پاسخ. خوشحالم که چنین هوشیارانه در حال دنبال کردن مقالات هستید، بله کاملا بیاد دارم، و تصمیم داشتم که اکنون بعنوان مثال دوم از بازیابی مطرح کنم. گرچه تفاوت خاصی ندارد، تنها اینبار بعنوان کلید (که در مثال اول یک عدد integer بود) باید یک آبجکت کلید (در این مثالی که شما ذکر کردید StudentKey) بعنوان آرگومان دوم پاس بدهید. ادامه مطلب را ملاحظه کنید.خب، در مثالی که تا به اینجای کار توسعه دادیم، کلید اصلی مرکب بود، من عینا کدهایی که باید برای بازیابی چنین رکوردی استفاده شود را برای شما کپی/پیست می‌کنم. لطفا خوب به کد‌ها بنگرید:کلاس Test:public class Test {
    public static void main(String[] args) {
        Student student;
        SessionFactory sessionFactory = new Configuration().configure(&quot;hibernate.cfg.xml&quot;)
                .addAnnotatedClass(Student.class)
                .buildSessionFactory();

        Session session = sessionFactory.getCurrentSession();

        session.beginTransaction();

        student = session.get(Student.class, new StudentKey(12345, 67890)); // به این خط توجه شود

        session.getTransaction().commit();

        System.out.println(student);

        session.close();
        sessionFactory.close();
    }
}خروجی را ملاحظه کنید:Student{studentKey=entities.StudentKey@6e019, name=&#039;Mohamad&#039;, tell=&#039;09121112233&#039;, favorites=[Book, Programming, Dancing], address=entities.Address@1255b1d1}همانطور که ملاحظه می‌کنید، براحتی رکورد مربوطه بازیابی شد.نحوه‌ی حذف (delete)اجازه دهید دیگر بدون پرگویی بگویم، برای حذف یک رکورد دو مرحله کار باید انجام داد: خواندن آن رکورد به کمک متد getحذف همان آبجکتی که بازیابی شده است به کمک متد deleteهمانطور که ملاحظه کردید، برای حذف از متد delete در کلاس Session استفاده می‌کنیم. به کد زیر توجه کنید، می‌خواهم تنها رکورد موجودی که در دیتابیس دارم را حذف نمایم!کلاس Test:public class Test {     
public static void main(String[] args) {         
Student student;         
SessionFactory sessionFactory = new Configuration().configure(&quot;hibernate.cfg.xml&quot;)                     .addAnnotatedClass(Student.class)                 
.buildSessionFactory();          
Session session = sessionFactory.getCurrentSession();         
session.beginTransaction();          

 student = session.get(Student.class, new StudentKey(12345, 67890));            student.setTell(&quot;0935936912&quot;);         
 session.delete(student);          
 
 session.getTransaction().commit();         
 session.close();         
 sessionFactory.close();    
 } }و خروجی لاگ:لاگ حذف (دو خط آخر)نکته‌ی جالب را توجه کردید؟ رکورد نه تنها از جدول student حذف شد، بلکه رکوردهای مرتبط آن نیز در جدول alaghemandiha نیز حذف شد.پرسش. هایبرنیت این کار را انجام می‌دهد؟ می‌توانیم این رفتار را کنترل کنیم؟پاسخ. بله، هایبرنیت اینکار را انجام می‌دهد. قطعا در این مثال بخصوص، ما رفتاری غیر از این را انتظار نداشتیم، اما بطور کلی بحثی بنام cascading وجود دارد که مربوط به مدیریت این بخش‌هاست. در قسمت‌های بعدی به آن می‌پردازیم.نحوه‌ی آپدیت (update)انجام عملیات بروز، مشابه عملیات delete است، یعنی ابتدا آبجکت مربوطه را از دیتابیس بازیابی می‌کنیم، سپس آن را به کمک متدهای setterهمان آبجکت تغییر می‌دهیم، و در نهایت از متد update استفاده می‌کنیم.فلذا برای آپدیت کردن از متد update در کلاس Session استفاده می‌کنیم. به مثال زیر توجه کنید، و دقیقا ببینید که چه رخ داده است. من خروجی + لاگ هایبرنیت را برای شما می‌آورم.کلاس Test:public class Test {
    public static void main(String[] args) {
        Student student;
        SessionFactory sessionFactory = new Configuration().configure(&quot;hibernate.cfg.xml&quot;)
                .addAnnotatedClass(Student.class)
                .buildSessionFactory();

        Session session = sessionFactory.getCurrentSession();
        session.beginTransaction();

        student = session.get(Student.class, new StudentKey(12345, 67890));
        student.setTell(&quot;0935936912&quot;);
        session.update(student);

        session.getTransaction().commit();
        session.close();
        sessionFactory.close();
    }
}به لاگ هایبرنیت مربوط به update توجه کنید:Hibernate: update Student set city=?, country=?, street=?, sname=?, stell=? where shomare_meli=? and shomare_shenasname=?و همچنین ببینید که در دیتابیس هم مقدار شماره‌تلفن تغییر کرده است:آپدیت شدن مقدار تلفن!پرسش. شما مدام میگید که متد فلان از کلاس Session! در صورتیکه اصلا Session کلاس نیست، یک رابط است. اشتباه خودتان را اصلاح کنید.پاسخ. خوشحالم که به گفته‌های من بسنده نکردید و خودتان جست‌وجو کردید. ابتدا بگویم که احتمال خطا در گفته‌های من زیاد است، و به این خاطر ازتون پوزش می‌خواهم.بله Sesssion یک interface است که با آبجکتی از کلاس SessionFactory مقداردهی می‌شود. اما از دید من خود رابط نیز نوعی کلاس است. ولی خوشحالم که متذکر شدید تا دوستان دیگر هم متوجه اصطلاحی که من بکار می‌برم شده باشند.سخن پایانیخب، حالا با عملیات CRUD هم آشنا شدید. وقت آن است که به یکی از جدی‌ترین بخش‌های هایبرنیت برویم. یعنی Relation Mapping. به من بگویید، آیا این مقاله توانسته نیاز شما رو برطرف سازد؟ توجه داشته باشید که برای نگارش این مقالات وقت خیلی زیادی صرف شده است، فلذا اهمیت زیادی برای من دارد تا بدانم آنطور که باید و شاید بکار می‌آید یا خیر.پایان بخش سوم.</description>
                <category>نشریه دایکه</category>
                <author>محمد عباسی</author>
                <pubDate>Thu, 09 May 2019 13:27:48 +0430</pubDate>
            </item>
                    <item>
                <title>مروری اجمالی به آنچه که هایبرنیت می‌کند - قسمت دوم</title>
                <link>https://virgool.io/dayche-group-Blog/hibernate-tutorial-part2-l8bslr8dt0zv</link>
                <description>در قسمت گذشته خلاصه‌ای از هایبرنیت خدمتتان ارائه دادم، و در نهایت یک آبجکت را در پایگاه‌داده به واسطه‌ی هایبرنیت Persist کردیم. به گمانم قسمت اول بسیار جذاب بود. امیدوارم آنطور که من انتظار داشتم مقاله‌ای کاربردی بوده باشه، اگر پیشنهادی یا انتقادی داشتید با من درمیان بگذارید. این اولین باری است که مطلبی فنی می‌نویسم و قطعا بی‌ایراد نخواهد بود.متاسفانه وقتی قسمت اول نزدیک به ۴۰۰۰ هزار واژه شد (که بیشتر بخاطر وجود سورس کدها هم بود) ویرایشگر متن بشدت کند شده بود، به همین خاطر بالاجبار مطالب را شکستم و در چند قسمت ارائه خواهم داد.در این قسمت به مباحث جدیدی خواهیم پرداخت.لینک قسمت‌های مرتبطقسمت اولفهرست مطالبویژگی‌های هایبرنیتراه‌اندازی هایبرنیت (بخش ۲)توضیح Annotationهای پایه‌ایویژگی‌های هایبرنیتقسمت پیش به خیلی از ویژگی‌های هایبرنیت اشاره کردیم. به گمانم پس از ملاحظه‌ی یک مثال عملی وقت آن است که کمی مفاهیم و واقعیت‌ها رو مرور کنیم.با هم مرور کردیم که هایبرنیت اصلی‌ترین امکانش، ORM یا همان نگاشت (Mapping) است. و با هم دیدیم چطور یک آبجکت Student به رکوردی در جدول student تبدیل شد. در آینده این نگاشت را بسیار مفصل‌تر بررسی خواهیم کرد. از قابلیت‌های مهم دیگر هایبرنیت مستقل از نوع دیتابیس بودن است. ما در هنگام کار با هایبرنیت به این توجه نمی‌کنیم که دیتابیس‌ MySQL است یا Oracle! این امکان فوق‌العاده‌ای است که هایبرنیت به ما می‌دهد. اما غیر از این‌ها دیگر چه؟هایبرنیت امکان Auto DDL دارد. زبان SQL را بیاد میاورید؟ زبان SQL از سه بخش عمده تشکیل شده است: DDL، DML و DCL. دستورات DDL مربوط به ساخت و حذف Schema می‌شوند. بیان ساده‌تر دستورات DDL مربوط به ساخت جداول و اعمال مشابه مربوط می‌شود. قسمت قبل را بیاد بیاورید، آیا ما برای اینکه جدول student را بسازیم کاری کردیم؟ جز این که مشخص کردیم این کلاس (Student) یک Entity است. با همین مشخصه، هایبرنیت عملیات مربوط به ساخت و تغییر یا بروز کردن آن را انجام می‌دهد. پس ساخت جداول به عهده‌ی هایبرنیت است.سوال. چه زمانی هایبرنیت جدول را می‌سازد و چه زمانی آپدیت می‌کند؟پاسخ. امیدوارم بودم تا رسیدن به بخش تنظیمات این سوال را نمی‌پرسیدید، چرا که در آنجا مشخص می‌کنیم که جداول create بشوند یا update یا حتا validate و... . اجازه دهید در جای مناسب خودش مفصل توضیح خواهم داد.هایبرنیت امکان Cache کردن را دارد. هایبرنیت کش کردن را در سه سطح انجام می‌دهد. در این خصوص صحبت خواهیم کرد.هایبرنیت امکانات بسیار خوب دیگری نظیر primary key generation، exception free و... را می‌دهد. جدا از آن‌ها یک زبان مستقل بنام HQL (Hibernate Query Language) را عرضه کرده و همچنین API های مناسبی برای Dynamic Queries. در خلل مثال‌ها سعی‌ خواهم کرد به آن‌ها بپردازم. راه‌اندازی هایبرنیت (بخش ۲)از اینجا به بعد مثال قسمت پیشین را بسط خواهیم داد و نکات مبهم آن را برطرف خواهیم کرد. در قسمت گذشته بارها توضیح موردی را به آینده موکول کردیم. امروز دقیقا وقت همان است که پاسخ آن‌ها را بدهیم.فایل کانفیگ را بیاد بیاورید (در گام۲ قسمت اول)، یکی از Propertyهای آن بنام hbm2ddl.auto بود. مقدار این خصوصیت را ما برابر با create گذاشتیم. می‌خواهیم اکنون به مقدارهایی بپردازیم که می‌توانیم به آن خصیصه اختصاص دهیم.مقدار create: وقتی برنامه اجرا می‌شود، و فایل کانفیگ خوانده می‌شود، اگر مقدار hbm2ddl.auto برابر با create باشد، فریمورک hibernate تمام جداول موجود در دیتابیس را (درصورت وجود) پاک می‌کند و دوباره ایجاد می‌کند. توجه داشته باشید که تمام اطلاعات موجود در دیتابیس ازبین خواهد رفت (drop می‌شود)، و دوباره جداول ساخته خواهد شد.بنابراین چنانچه دیتایی در جداول خودتان دارید باید نسبت به استفاده از این مقدار هوشیار باشید. چون سطرهای جداول دوباره برنخواهند گشت، صرفا جدول را دوباره خواهد ساخت.پس در واقع مقدار create دو کار را انجام می‌دهد: جداول موجود را پاک می‌کند.جداول جدیدی را ایجاد می‌کند.حالا می‌دانید که اگر قصد آموزش و آزمایش ندارید، استفاده از این مقدار خطرناک است (خطر از دست دادن دیتا). معمولا تنها زمانی از این مقدار استفاده می‌کنند که می‌خواهند schemaی جداول را ایجاد کنند. ولی هنگامی که دیتایی درون دیتابیس وارد شد دیگر این مقدار را استفاده نخواهند کرد. چه مقداری را استفاده می‌کنند؟ همراه باشید!مقدار update: شما می‌توانید بجای استفاده از create مقدار update را قرار دهید. این مقدار در صورت اجرای مجدد دیگر جداول موجود را پاک نخواهد کرد. رفتاری روشنفکرانه دارد. بطور دقیق، هایبرنیت وقتی با این مقدار تنظیم شده باشد ملاحظه می‌کند، اگر جدولی در دیتابیس وجود ندارد، ولی در جاوا Entity برای آن ساخته شده است، آن جدول را ایجاد می‌کند. ما برنامه را همواره توسعه می‌دهیم و ممکن است Entityهای زیادی را اضافه کنیم که بخواهیم درهنگام اجرا، جداول مربوطه‌ی آنها ایجاد شود و مشکلی هم برای جداول از پیش تعیین شده (برای Entityهای قدیمی) پیش نیاید. مقدار update برای ما چنین می‌کند.یکی دیگر از کارهایی که مقدار update انجام می‌دهد، ملاحظه می‌کند کدام Entity قدیمی تغییر کرده است (بعنوان مثال فیلدی به آن اضافه شده است که در نتیجه باید ستونی به جدول مربوطه‌اش اضافه شود). مقدار update تمام جداولی را که باید تغییر کنند را نیز alter می‌کند. بعبارتی جداول را بروز می‌کند.پس درواقع مقدار update دو کار انجام می‌دهد: اگر جدول مربوطه به Entityای وجود نداشته باشد، آن را ایجاد می‌کند.۲.   اگر جدول مربوط به Entityای تغییر کرده باشد، آن را تغییر می‌دهد.یک کار سومی نیز انجام می‌دهد: به entityهایی که جداول متناظرشان وجود دارد و نیازی به تغییر ندارند، دست نمی‌زند!مقدار create-drop: این مقدار رفتار جالبی دارد. ابتدا تمام جداول را پاک می‌کند (درصورت وجود) بعد همچون مقدار create، آنها را ایجاد می‌کند، و پس از آن که کار به اتمام رسید دوباره آن‌ها را پاک میکند.مقدار validate: این مقدار در واقع فقط چک می‌کند که آیا mapping schema (همان کلاس‌های ما با Annotationهای مربوطه‌اش) با table schema که در دیتابیس قرار دارد هماهنگ هستند یا خیر. و هیچ کار اضافه‌ای انجام نخواهد داد.وقتی که برنامه از حالت development به حالت production می‌رود، معمولا این مقدار (validate) را برای تنظیمات هایبرنیت درنظر می‌گیرند.خب، تا اینجای کار مقدار hbm2ddl.auto را برابر با update قرار دهید تا با ری‌استارت‌ کردن‌های مجدد برنامه اطلاعات دیتابیس پاک نشود و به ادامه‌ی توضیح مثال قبل بپردازیم.من تصویر مثال قبل را دوباره در این قسمت نیز آپلود می‌کنم:آزمودن هایبرنیت، به خروجی توجه کنید!اول اجازه دهید که تاکید کنم هنگام استفاده از هایبرنیت توجه ویژه‌ای به لاگ‌های خود فریمورک داشته باشید. هایبرنیت بطور کامل توضیح می‌دهد که دقیقا چه دستوراتی را اجرا می‌کند، و عملا چه رفتاری دارد.متاسفانه من حوصله‌ی تحلیل لاگ را ندارم، ولی چیزی نیست که از عهده‌ی آن برنیایید.پرسش. من وقتی هایبرنیت را اجرا می‌کنم هیچ چیز راجع به دستورات SQL نمایش نمی‌دهد!پاسخ. احتمالا مقدار show_sql در فایل کانفیگ را برابر با false قرار دادید. همانطور که در فایل کانفیگ مشاهده می‌کنید ما این مقدار را برابر با true قرار دادیم.پرسش. من Entityای بنام hibernate_sequence نساخته‌ام، با این وجود یک جدول به این نام در دیتابیس من وجود دارد، و هربار هم عملیات insert را انجام می‌دهم ابتدا یک مقداری در این جدول آپدیت می‌شود. این چه جدولی است؟پاسخ. خوشحالم که به لاگ‌های هایبرنیت هوشیارانه نگرسته‌اید. بله، این جدول را هایبرنیت خودش برای مدیریت یکتایی مقدار در فیلد id درست کرده است. زمانی که ما از Annotation تولید مقادیر (یعنی @GeneratedValue) استفاده می‌کنیم این اتفاق میافتد. ولی می‌توانستیم استراتژی مشخصی برای GeneratedValue در نظر بگیریم. بطور مثال وقتی در MySQL از مقدار @GeneratedValue(strategy = GenerationType.IDENTITY) استفاده می‌کنیم، دیگر این جدول کمکی ایجاد نمی‌شود. چند و چون و استراتژی‌های مختلف را شرح خواهم داد. در هر حال توجه ویژه شما به لاگ‌ها شایسته‌ی تقدیر است.هر عملیاتی که با هایبرنیت انجام می‌دهیم، می‌بایست در یک تراکنش مشخص باشد. نگران نباشید، این جمله را کاملا توضیح خواهم داد.به تصویر توجه بکنید، ما یک Session از کلاس SessionFactory میگیریم (Session session = sessionFactory.getCurrentSession). سپس با استفاده از‌ آن آبجکت یک تراکنش را شروع می‌کنیم (session.beginTransaction). بطور محاوره، از اینجا تا زمانی که تراکنش شده را کامیت می‌کنیم (session.getTransaction().commit)، میتوانیم عملیات خود را با دیتابیس انجام دهیم (درج کنیم، حذف کنیم، تغییر دهیم و یا بازیابی کنیم). در این مثال یک درج ساده انجام داده‌ایم (از متد save استفاده کردیم).از زمان شروع تراکنش تا زمان کامیت آن، آبجکت در وضعیت persistence قرار می‌گیرد. این وضعیت را بعدا توضیح می‌دهم.پرسش. شما با گفتن بعدا توضیح می‌دهم، حس بدی را به ما منتقل می‌کنید. حس نفهمیدن، و حس اینکه کلی مباحث دیگر مانده است که ما نمی‌دانیم.پاسخ. متاسفانه این حس را نیز من دارم (کلی مباحث مانده که من نمی‌دانم)، ولی از اینکه حس بدی به شما منتقل شده است متاسفم، هدف من این است که دست‌کم اشاره به تمام موضوعات (تا جایی که خودم می‌دانم) بکنم، تا بتوانید جست‌و‌جو کنید. برای اینکه باور کنید حالت‌های آبجکت در هایبرنیت هم چیز عجیب و غریبی نیست، توضیح مختصری می‌دهم.در هایبرنیت آبجکت ۳ وضعیت کلی دارد:۱. وضعیت transient: زمانی که آبجکت با عملگر new ساخته می‌شود و هیچ ارتباطی با هایبرنیت ندارد!۲. وضعیت persistant: زمانی که آبجکت دقیقا درگیر با Session هایبرنیت است.۳. وضعیت detached: زمانی که آبجکت از از session حذف می‌شود.شفاف نبود؟ عیبی ندارد. کارایی اصلی دانستن این موضوع بیشتر در رابطه با بحث Caching است، پس مفصل خواهیم گفت.دوست دارید به کدام مبحث بپردازیم؟ بحث CRUD در هایبرنیت؟ یا کمی Annotationهای پایه‌ای را معرفی کنیم؟ هر دو مبحث جذاب هستند، اما اصلا قابل قیاس با جذابیت بحث Association Mapping نیست!توضیح Annotationهای پایه‌ایخب، تصمیم گرفته شد! البته حتما پیش‌تر توی فهرست مطالب خوانده بودید و من آنگونه که باید نتوانستم شما را سوپرایز کنم!@Tableاین Annotation اطلاعاتی در رابطه با اینکه جدول ساخته شده از یک Entity مشخص چگونه باید باشد را می‌دهد! البته صرفا در مورد نام آن تصمیم می‌گیرد. با تغییر پارامتر name در آن می‌توانید نام جدول را نامی دلخواه بگذارید:@Table(name=&quot;my_table_name&quot;)@Entityاین Annotation را باز هم خواهیم دید، اما اینجا یک اشاره کوتاه به آن کنیم. این Annotation نیز پارامتری بنام name دارد که نام Entity را تغییر می‌دهد. توجه کنید که نام Entity با نام جدول متفاوت است. نام جدول چیزی است که دیتابیس می‌شناسد و با آن کار می‌کند. اما نام Entity چیزی است که جاوا می‌شناسد. اگر این نام را تغییر دهید، دیگر همیشه باید با نام تغییر شده در کدهای جاوا آن را صدا کنید. گیج کننده شد؟ عیبی ندارد، مثالش را خواهید دید.پرسش. درست است که گفتید اگر متوجه نشدید عیبی ندارد، اما دقیقا یعنی چی؟ یعنی نام کلاس جاوا تغییر می‌کند؟پاسخ. خیر، نام کلاس جاوا تغییر نمی‌کند. بطور پیش‌فرض نام Entity همان نام کلاس جاوا است. بطور مثال کلاس Student نام Entityاش Student است. ولی وقتی تغییر دهیم، نام Entity دیگر نام پیش‌فرض نخواهد بود.بخاطر دارید که در قسمت فلسفه‌ی هایبرنیت گفتم که مزیت اصلی هایبرنیت آن است که رویکرد شی‌گرا را حفظ کنیم؟ و بدون آنکه دیتابیس را مدنظر قرار دهیم به برنامه‌نویسی بپردازیم؟ مسئله همین جاست. بطور مثال ما در زبان HQL از نام Entity استفاده می‌کنیم که بطور پیش‌فرض نام کلاس است (بدون توجه به نام جدول)، وقتی نام Entity را تغییر می‌دهیم باید حواسمان همیشه جمع باشد که دیگر با نام تغییر کرده از آن در کد های جاوا استفاده کنیم (هرجا که نیاز به نام Entity هست، مثلا در استفاده از HQL)@SecondaryTable(name=&quot;second_table&quot;)@SecondaryTables({@SecondaryTable(name=&quot;second_table&quot;),                     @SecondaryTable(name=&quot;another_second_table&quot;)})خیلی وقت‌ها جداول دیتابیس آماده هستند و ما مجبور هستیم کلاس‌هایمان را با آن منطبق کنید. بطور مثال ممکن است یک کلاس جاوا، شامل ۲ جدول در دیتابیس باشد. چطور باید آن Entity را به ۲ جدول تقسیم کنیم؟ یا حتا بیشتر. اگر صرفا یک جدول اضافه هست (در مجموع ۲ جدول) کافی است از @SecondaryTable استفاده کنیم و نام جدول دوم را بدهیم. اگر بیش از ۲ جدول بود میباست از @SecondaryTables استفاده کنیم که یک &quot;s&quot; جمع دارد. و نوع استفاده از آن را در عنوان آورده‌ام. حال چگونه بگوییم کدام فیلد برای کدام جدول است؟ از @Column استفاده می‌کنیم. در @Column خصیصه‌ای هست بنام table که مقدار نام جدول دوم را برای آن در نظر می‌گیریم. اگر هیچ مقداری لحاظ نکنیم، بطور پیش‌فرض آن فیلد برای جدول اصلی درنظر گرفته می‌شود:@Entity@SecondaryTables({        @SecondaryTable(name = &quot;city&quot;),        @SecondaryTable(name = &quot;country&quot;)})public class Address {    @Id    private Long id;    private String street1;    private String street2;    @Column(table = &quot;city&quot;)    private String city;    @Column(table = &quot;city&quot;)    private String state;    @Column(table = &quot;city&quot;)    private String zipcode;    @Column(table = &quot;country&quot;)    private String country;    // Constructors, getters, setters}این تکه کد را از کتاب Beginning Java EE 7 برداشته‌ام. خوب به آن توجه کنید.سوال، وقتی نگاشت مثال بالا صورت بگیرد، چه اتفاقی میافتد؟ لطفا در کامنت‌ها برای من بگویید.کلیداصلی مرکبخب، بنظور داشتن یک کلید مرکب، میتوان از قابلیت @Embeddable در JPA استفاده کرد. کلاسی را که Embeddable در نظر می‌گیریم می‌بایست حتما از قوانین JavaBeans پیروی کند. بعبارتی باید حتما یک سازنده‌ی بدون آرگومان (no-args constructor) داشته باشد، بهمراه متدهای getter و setter و همچنین متدهای equals و hashCode. نکته‌ی مهم دیگر اینکه کلاس Embeddable نباید هیچ کلیدی داشته باشد. بعبارتی فیلدی از آن نباید انوتیشن @Id داشته باشد. و اما چطور کار می‌کند؟ اجازه دهید ابتدا یک کلاس را بعنوان Embeddable ایجاد کنیم.پس از ایجاد این کلاس، یک فیلد از جنس همین کلاس در کلاس مقصد (جایی که می‌خواهیم کلیدمرکب داشته باشیم) ایجاد می‌کنیم.اگر گیج شده‌اید نگران نباشید، به مثالی که میزنم خوب دقت کنید. ما می‌خواهیم کلاس Student کلیدی مرکب داشته باشد، به این معنا که ترکیب کدملی و شماره‌شناسنامه‌ی داشنجو را بعنوان کلید درنظر بگیریم. تمام اطلاعات دیگر دانشجو هم سرجای خودش باقی بماند. حال چکار باید بکنیم؟ اولین کار ایجاد کلاس کلید! و دومین کار، تزریق آن به کلاس Student.توجه کنید که کلاس Embeddable باید اینترفیس Serializable را impelement کند!من تک تک کلاس‌ها را برای شما می‌گذارم، با دقت نگاه کنید، چرا که نسبت به مثال‌های پیشین اندکی تغییر داشته است.کلاس StudentKey:package entities;

import javax.persistence.Column;
import javax.persistence.Embeddable;
import java.io.Serializable;

@Embeddable
public class StudentKey implements Serializable {

 @Column(name = &quot;shomare_meli&quot;)
    private int nationalId;
 @Column(name = &quot;shomare_shenasname&quot;)
    private int sid;

    public StudentKey() { }

    public StudentKey(int nationalId, int sid) {
        this.nationalId = nationalId;
        this.sid = sid;
    }

    public int getNationalId() {
        return nationalId;
    }

    public void setNationalId(int nationalId) {
        this.nationalId = nationalId;
    }

    public int getSid() {
        return sid;
    }

    public void setSid(int sid) {
        this.sid = sid;
    }

 @Override
 public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        StudentKey that = (StudentKey) o;

        if (nationalId != that.nationalId) return false;
        return sid == that.sid;
    }

 @Override
 public int hashCode() {
        int result = nationalId;
        result = 31 * result + sid;
        return result;
    }
}کلاس Student:package entities;
import com.sun.istack.internal.NotNull;
import javax.persistence.*;

@Entity
public class Student {
    @EmbeddedId
    private StudentKey studentKey;
    @Column(name = &quot;sname&quot;)
    private String name;
    @Column(name = &quot;stell&quot;)
    private String tell;
    private String address;

    public Student(StudentKey studentKey, String name, String tell, String address) {
        this.studentKey = studentKey;
        this.name = name;
        this.tell = tell;
        this.address = address;
    }
    public StudentKey getStudentKey() {
        return studentKey;
    }
    public void setStudentKey(StudentKey studentKey) {
        this.studentKey = studentKey;
    }
    public Student() {} // non-arg constructor
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getTell() {
        return tell;
    }
    public void setTell(String tell) {
        this.tell = tell;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
}کلاس Test:import entities.Student;
import entities.StudentKey;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class Test {
    public static void main(String[] args) {
        StudentKey studentKey = new StudentKey(12345,67890);
        Student student = new Student(studentKey,&quot;Mohamad&quot;, &quot;09121112233&quot;, &quot;Tehran&quot;);

        SessionFactory sessionFactory = new Configuration().configure(&quot;hibernate.cfg.xml&quot;)
                .addAnnotatedClass(Student.class)
                .buildSessionFactory();

        Session session = sessionFactory.getCurrentSession();
        session.beginTransaction();

        session.save(student);

        session.getTransaction().commit();
        session.close();
        sessionFactory.close();
    }
}تصویر ساختار پروژهساختار پروژهمی‌توانید عینا کدها را کپی/پیست کنید، گرچه توصیه می‌شود که بنویسید تا بهتر درک کنید. خروجی کد بالا را میتوانید در دیتابیس من ببینید:خروجی کد بالابجای استفاده از انوتیشن‌های @Embeddable و @EmbeddedId می‌توانستیم از @IdClass استفاده کنیم. شما به من بگویید استفاده از آن چگونه است!خب، با توجه به اینکه دوباره میزان کلمات استفاده شده در این پست زیاد شده است، ادیتور متن ویرگول سنگین شده است و سرعت تایپ من را پایین آورده است، باید این مطلب را ببندم و برای ادامه پست دیگری را باز کنم.دوستان عزیزم به من بگویید که نظر شما در رابطه با این مطالب چیست. آیا چیزی دستگیرتان می‌شود یا مباحث همچنان برایتان گنگ است؟ نظرات شما کمک شایانی به من می‌کند. موفق باشید.پایان قسمت دوم.</description>
                <category>نشریه دایکه</category>
                <author>محمد عباسی</author>
                <pubDate>Wed, 08 May 2019 19:46:16 +0430</pubDate>
            </item>
                    <item>
                <title>مروری اجمالی به آنچه که هایبرنیت می‌کند - قسمت اول</title>
                <link>https://virgool.io/dayche-group-Blog/%D9%85%D8%B1%D9%88%D8%B1%DB%8C-%D8%A7%D8%AC%D9%85%D8%A7%D9%84%DB%8C-%D8%A8%D9%87-%D8%A2%D9%86%DA%86%D9%87-%DA%A9%D9%87-%D9%87%D8%A7%DB%8C%D8%A8%D8%B1%D9%86%DB%8C%D8%AA-%D9%85%DB%8C%DA%A9%D9%86%D8%AF-%D9%82%D8%B3%D9%85%D8%AA-%D8%A7%D9%88%D9%84-pkqvy2sqhtfn</link>
                <description>در این مقاله قصد دارم از ارتفاع ۱۰هزارپایی به کلیت هایبرنیت نگاهی بیاندازم تا شاید بتوان حدودی مشخص برای آن تعیین کرد. گرچه بمنظور عملی بودن مقاله، در خیلی مواقع فرودی اضطراری خواهیم داشت. اگر بتوانم به این هدف دست یابم، احتمالا کار خود و دیگر دوستانی که بدنبال مباحث Hibernate و بطور کلی ORMها هستند را راحت‌تر کرده‌ام.فهرست مطالبفلسفه‌ی هایبرنیتراه‌اندازی هایبرنیتفلسفه‌ی هایبرنیتهایبرنیت چیست و چکار می‌کند؟ این اولین پرسشی است که باید به آن پاسخ داد. در مورد فلسفه‌ی هایبرنیت مطالب فارسی و انگلیسی بسیاری وجود دارد، به این خاطر اشاره من به آن کوتاه، مختصر و خلاصه خواهد بود.هایبرنیت یک فریمورک برای ذخیره‌سازی و بازیابیِ آبجکت‌های جاوا درون پایگاه‌داده است. تکرار می‌کنم، هایبرنیت ابزاری است که Java Objectها را درون پایگاه‌داده Persist / Save می‌کند و طبعا در زمان مورد نیاز Retrieve می‌کند.تاکید من بر Java Objectها از این منظر است که تفاوتی جدی بین JDBC و فریمورک هایبرنیت قائل شویم. گرچه خود این فریمورک در نهایت از درایور JDBC برای ارتباط با پایگاه‌داده استفاده می‌کند، اما این امکان را به ما می‌دهد که با رابطی متفاوت، رویکرد شی‌گرای خودمان را حفظ کنیم.اگر هیچ اطلاعی از پیش راجع به هایبرنیت نداشته‌اید، و مطالب بالا را گنگ و بی‌معنی می‌بینید، تنها یک توصیه به شما دارم: باید تحمل و صبر بیشتری بخرج دهید. من فقط می‌توانم قول دهم که به محض دست به کد شدن تمام گرفتاری‌های ذهنی راجع به فلسفه‌ی هایبرنیت برایتان برطرف خواهد شد، و کافی است بعد از آن یکبار دیگر این مقدمه‌ی کوتاه را مطالعه کنید تا بنظرتان شفاف و گویا بیاید. همراه باشید!وقتی صحبت از هایبرنیت می‌کنم،‌ منظورم دقیقا به فریمورک ORM آن است. احتمالا شما نیز چنین برداشتی را کرده بودید که صحبت از چیست. اما در سایت هایبرنیت تاکید کرده است که هایبرنیت بیشتر از یک فریمورک ORM (یا همان Object Relational Mapping) است. فلذا مجددا تاکید می‌کنم که هدف این مقاله شرح Hibernate ORM می‌باشد.هایبرنیت فریمورک‌‌های دیگری نظیر Validator ، Search ، OGM و... را دارد. فریمورک ORM مخصوص عملیات نگاشت بین آبجکت‌های جاوا و پایگاه‌داده‌ی رابطه‌ای است. بعبارت  دیگر هایبرنیت مابین پایگاه‌داده‌ی رابطه‌ای و آبجکت‌های جاوا قرار می‌گیرد و آن‌ها را بهم تبدیل می‌کند. پرسش. آیا هایبرنیت فقط برای پایگاه‌داده‌های رابطه‌ای نظیر MySQL, SQL Server و Oracle است؟ پس برای پایگاه‌داده‌های غیر رابطه‌ای نظیر MongoDB نمی‌توان از هایبرنیت استفاده کرد؟پاسخ. اگر منظور شما از هایبرنیت، Hibernate ORM است، باید به پرسش اول بگویم بله، Hibernate ORM فقط برای پایگاه‌داده‌های رابطه‌ای است نظیر همان‌هایی که گفتید و ده‌ها سیستم پایگاه‌داده‌ایِ رابطه‌ای دیگر! و به پرسش دوم باید بگویم خیر، نمیتوان از آن برای MongoDB استفاده کرد. ولی می‌توان از Hibernate OGM که برای نگاشت گراف‌ها طراحی شده است برای این منظور استفاده کرد.پرسش. آیا Hibernate OGM در این مقاله شرح داده‌ خواهد شد؟جواب. خیر، فقط فریمورک ORM را بررسی خواهیم کرد. به همین خاطر در هر کجای مقاله زمانی که صحبت از هایبرنیت است دقیقا منظورم Hibernate ORM می‌باشد. و به همین ترتیب، هرجا صحبت از پایگاه‌داده می‌کنم منظورم پایگاه‌داده‌های رابطه‌ای است.همانطور که عرض کردم، هایبرنیت مابین پایگاه‌داده و آبجکت‌های جاوا ایستاده است و عملیات Mapping را انجام می‌دهد. از آنجایی که دیگر ما نگران این نیستیم که چطور قرار است در پایگاه‌داده ذخیره‌سازی انجام دهیم، کاملا با رویکرد شی‌گرای خودمان کار را پیش می‌بریم. بدون هایبرنیت برنامه‌نویس خودش مجبور است که نگاشت بین آبجکت‌ها و موجودیت‌های سمت پایگاه‌داده را انجام دهد. و اینکار جدا از اینکه پیچیدگی‌های خود را می‌داشت، از نظر مفهومی ممکن بود اهرم فشاری باشد تا برنامه‌نویس در طول کار در بعضی موارد رویکرد شی‌گرا را از دست بدهد.https://www.javaguides.net/2018/12/what-is-difference-between-hibernate-and-spring-data-jpa.htmlپرسش. چرا نیاز به Mapping است؟پاسخ. ما باید اطلاعات برنامه‌ی خودمان را در پایگاه‌داده ذخیره کنیم. در سمت کد‌های جاوا، ما با مفاهیمی بنام property، کلاس و آبجکت طرف هستیم و در سمت پایگاه‌داده با مفاهیمی نظیر سطر، ستون، صفت، جدول و تاپل (tuple) طرف هستیم. به عبارت دیگر ما باید یک کلاس را به یک جدول تبدیل کنیم، و هر آبجکت را به تاپلی (سطر) از جدول نگاشت کنیم.جدا از این‌ها، ما در سمت جاوا، مفاهیم دیگری نظیر وراثت و ارتباط Composition را داریم، در سمت پایگاه‌داده مفاهیم ارتباط بین موجودیت‌ها و چندی رابطه (Cardinality) را داریم. برگردیم به سوال، چه نیازی به نگاشت است؟ ما باید اطلاعاتی که در سمت جاوا بدست می‌آید را درون پایگاه‌داده ذخیره کنیم و اطلاعاتی را که درون پایگاه‌داده ذخیره شده است را بتوانیم به کد‌های جاوا بیاوریم. چطور این‌ها را باید بهم نگاشت کرد؟ هایبرنیت این کار را برای ما انجام می‌دهد.از قابلیت‌های خوب دیگر که هایبرنیت به ما می‌دهد (بغیر از ORM که توضیح داده شد)، این است که میزان کدهای نوشته شده توسط برنامه‌نویس نسبت به jdbc به شدت کاهش پیدا می‌کند. اما از آن مهمتر اینکه هایبرنیت برنامه‌نویسی را کاملا از مدل دیتابیس مستقل می‌کند. این امکان فوق‌العاده به شما اجازه میده که بدون اندیشیدن به آن که قرار است با چه پایگاه‌داده‌ای کار کنید (Mysql باشد یا Postgresql؟ فرقی نمیکند) کد بزنید و نگران نوع نگاشت آن نباشید (بر عهده‌ی هایبرنیت است). بعبارتی شما می‌توانید بدون هیچ هزینه‌ای و فقط با تغییری کوچک در یک فایل تنظیمات، دیتابیس خود را بطور مثال از Oracle به MySQL تغییر دهید.و اما آخرین نکته‌ای که باید در قسمت فلسفه‌ی هایبرنیت گفت؛ در اصل هایبرنیت یک پیاده‌سازی (implementation) از یک استاندارد دیگر است. بعبارتی JPA  (یا همان Java Persistence API) یک استاندارد است که چگونگی نگاشت و تمام آنچه که مربوط به مبحث ORM می‌شود را در خودش مشخص کرده است، و هایبرنیت یک فریمورک است که این استاندارد را اجرا کرده است. فلذا ما هنگام استفاده از هایبرنیت ناگزیر هستیم JPA را نیز تاحدودی بشناسیم، و از آن استفاده کنیم. البته کاملا مشخص است که این دو، جدا از هم نیستند. JPA استاندارد ( یا به عبارتی interface) و هایبرنیت پیاده‌سازی (implementation) است.اطلاعات بیشتر راجع به JPA را در اینترنت جست‌وجو کنید. هرآنچه که این مقاله به آن نیاز داشته باشد را در خلل مثال‌ها توضیح خواهد داد، و دیگر توضیحی مستقل راجع به JPA نخواهیم داشت.می‌توان برای اطلاعات بیشتر به فصل ۴، فصل ۵ و فصل ۶ کتاب Beginning Java EE 7 نوشته‌ی آقای Goncalves مراجع کنید.راه‌اندازی هایبرنیتخب، تا اینجای کار توضیح دادم که هایبرنیت چیست و قرار است برای ما چکاری انجام دهد. حال باید راجع به چگونگی آن صحبت کنم.می‌خواهم خیلی زود و با کم‌ترین مقدمه دست‌بکار شویم، و خودمان را کمی درگیر کدنویسی کنیم. سپس اطلاعات بیشتر را بعد از آن ارائه دهم.فرایند راه‌اندازی هایبرنیت بصورت گام به گام!گام۰. آماده‌سازی محیطگام۱. اضافه کردن کتابخانه‌های موردنیاز به پروژه.گام۲. اضافه کردن فایل تنظیماتِ هایبرنیت به پروژه.گام۳. آماده کردن کلاس‌های جاوا برای نگاشت به دیتابیس.گام۴. اجرای عملیاتهای پایگاه‌داده‌ای.گام۰. آماده‌سازی محیطگام صفر را ساخت پروژه و آماده‌سازی دیتابیس درنظر بگیرید. برای من اهمیت ندارد که شما در چه محیطی کد می‌نویسید، یا روی چه پروژه‌ای کار می‌کنید. آیا وب‌اپلیکیشن می‌نویسید؟ یا یک برنامه‌ی کنسول؟ این‌ها در نوع استفاده از هایبرنیت اهمیت ندارد. گرچه بطور مثال اگر از Spring Boot استفاده می‌کنید می‌توانید از Starter های مروبط به JPA استفاده کنید و عملا گام ۱ را حذف کنید. ولی در هر حال پیشنهاد می‌کنم نوع کانفیگ را بیاموزید، تا بتوانید در هر نوع پروژه‌ای آن را بکار بگیرید. چنانچه از عهده‌ی این کار برنیامدید پس از خواندن این بخش (راه‌اندازی هایبرنیت) مشخصا نوع نیاز خودتان را سرچ کنید. بعنوان مثال هایبرنیت با Spring Boot.من برای مدیریت پروژه از Maven استفاده می‌کنم، پیشنهاد می‌کنم شما هم چنین کنید، یا از Gradle استفاده کنید. استفاده از Maven جدا از مزیت‌هایش، پروژه را مستقل از ide نیز می‌کند (بعبارتی IDE Agnostic). اگر نمی‌دانید Maven چیست در یوتیوب سرچ کنید و آن را یادبگیرید.پس پروژه‌ی خود را هر طور که صلاح می‌دانید بسازید. حال به سراغ پایگاه‌داده برویم.خب، از چه پایگاه‌داده‌ای استفاده کنیم؟ این بار هم هر طور صلاح می‌دانید تصمیم بگیرید. اگر از Oracle استفاده می‌کردید، الان هم می‌توانید استفاده کنید. تنها الزام این بخش آن است پایگاه‌داده باید رابطه‌ای باشد. تکرار می‌کنم هایبرنیت تقریبا تمام RDBMSها را پشتیبانی می‌کند. چنانچه از دیتابیس متداولی استفاده نمی‌کنید و نگران هستید که آیا هایبرنیت از آن پشتیبانی می‌کند یا خیر، می‌توانید در این باره نیز سرچ کنید. من از MySQL استفاده می‌کنم. حال باید یک پایگاه‌داده درون MySQL بمنظور استفاده در این پروژه ایجاد کنم. اینکه چطور این کار را می‌کنید هم باز بخودتان مربوط است، از محیط‌های گرافیکی استفاده می‌کنید یا دستوری، فرقی ندارد. عملا این بخش اصلا ارتباطی با هایبرنیت ندارد از لحاظ مفهومی. من دستور زیر را در کنسول MySQL می‌نویسم:CREATE DATABASE hibernate;خب تقریبا مطمئن هستم که تمام RDBMSها این دستور را پشتیبانی می‌کنند. بعد از آن که مطمئن شدم پایگاه‌داده به درستی ایجاد شده است به سراغ گام بعدی می‌رویم. برای مطمئن شدن نیز می‌توانید دستور زیر را بزنید تا لیستی از تمام دیتابیس‌ها داشته باشید. همراه باشید!SHOW DATABASES;گام۱. اضافه کردن کتابخانه‌های موردنیاز به پروژهطبعا نیاز است تا JAR فایل‌ها یا همان کتابخانه‌های هایبرنیت را به پروژه اضافه کنیم. برای اینکار می‌توان به صفحه‌ی هایبرنیت رفت و آن را دانلود کرد. توجه کنید که بهتر است نسخه‌ی stable را دانلود کنید. در زمان نگارش این مقاله نسخه‌ی ۵ پایدار است و نسخه‌ی ۶ در حال توسعه می‌باشد. زمانی که فایل zip را دانلود کردید، به پوشه‌ی lib روید. در آن پوشه یک پوشه‌ی دیگر بنام required وجود دارد. تمام آن JAR فایل‌هایی که ما برای پروژه‌ی خود نیاز داریم در آن وجود دارد. بعبارتی می‌توان از تمام آنچه دانلود کردیم فقط این پوشه را به class path خود اضافه کنیم. از چه محیطی برای کد زدن استفاده می‌کنید؟ eclipse یا IntelliJ IDEA؟ یا چه ابزاری برای مدیریت وابستگی‌ها؟ maven؟ gradle؟ هیچ‌کدام؟ قطعا بیاد دارید که گفتم این‌ها به این مقاله مرتبط نیست، بسته به نوع سلیقه و ذائقه‌ی خودتان رفتار کنید. من از IntelliJ و Maven استفاده می‌کند. بر اساس نوع سلیقه‌ی خودتان کتابخانه‌ای که به آن اشاره کردیم را به پروژه‌ی خودتان اضافه کنید. من از Maven استفاده می‌کنم درنتیجه به فایل POM در پروژه وابستگی زیر را اضافه می‌کنم:&lt;dependency&gt;
    &lt;groupId&gt;org.hibernate&lt;/groupId&gt;
    &lt;artifactId&gt;hibernate-core&lt;/artifactId&gt;
    &lt;version&gt;5.2.17.Final&lt;/version&gt;
&lt;/dependency&gt;خب یک چیز دیگر باقی مانده است. قطعا از بخش فلسفه‌ی هایبرنیت بخاطر دارید که اشاره کردم هایبرنیت در نهایت و دور از چشم ما، از JDBC استفاده می‌کند. فحوای کلامم این است که باید درایور مربوط به دیتابیس را هم اضافه کنیم (در این جا MySQL). ما نیاز به JAR فایلِ MySQL Connector داریم. آن را به هر شکل که می‌دانید به پروژه‌ی خودتان اضافه کنید. من هم باید فایل POM را با وابستگی زیر بروز کنم:&lt;dependency&gt;
    &lt;groupId&gt;mysql&lt;/groupId&gt;
    &lt;artifactId&gt;mysql-connector-java&lt;/artifactId&gt;
    &lt;version&gt;8.0.11&lt;/version&gt;
&lt;/dependency&gt;خب بنظر دیگر کار تمام شد. ساده‌تر از آن چیزی بود که شاید فکرش را می‌کردید. اجازه دهید خلاصه کنم تا برای همیشه بیادتان بماند و سپس به سراغ گام بعدی برویم. در این بخش ۲ چیز نیاز داشتیم: کتاب‌خانه‌های مربوط به هایبرنیتکتاب‌خانه‌ی مربوط به اتصال jdbc به پایگاه‌دادهگام۲. اضافه کردن فایل تنظیماتِ هایبرنیت به پروژهو اما شروع کار با خود هایبرنیت. هایبرنیت برای این که بداند به کدام دیتابیس متصل شود و چه رفتاری داشته باشد، به یک فایل کانفیگ استناد می‌کند.ساختار پروژه تاکنونساختار پروژه‌ی من تاکنون چنین است. یک فایل xml بنام hibernate.cfg.xml در دایرکتوری resources ایجاد می‌کنم. این فایل hibernate.cfg.xml دقیقا همان فایل کانفیگی است که هایبرنیت به آن استناد می‌کند. شما اگر از maven استفاده نمی‌کنید در همان دایرکتوری src این فایل را بسازید.پرسش. آیا حتما نام این فایل باید hibernate.cfg.xml باشد؟ یا جایش حتما باید مشخص باشد؟پاسخ. خیر. میتوان نام دلخواهی برای آن گذاشت، یا در هر جایی از پروژه قرار داد. نام و مکان پیش‌فرض به ما کمک می‌کند تا بدون گفتن مکان و نام فایل، فریمورک هایبرنیت آن را پیدا کند. در غیراین صورت باید بطور شفاف به هایبرنیت بگوییم که فایل تنظیمات نامش چیست و در کجا قرار گرفته. در پروژه‌های معمولی مسیر پیش‌فرض src می‌باشد و نام hibernate.cfg.xml و در پروژه‌های maven نیز همچنین، با این تفاوت که مسیر پیش‌فرض دایرکتوری resources می‌باشد.و اما محتویات این فایل. همانطور که گفتم یک فایل تنظیمات xml است، که dtd مشخص دارد. من فایل را برای شما می‌گذارم و سپس اجزای آن را شرح می‌دهم.
&lt;!DOCTYPE hibernate-configuration PUBLIC
        &quot;-//Hibernate/Hibernate Configuration DTD 3.0//EN&quot;
        &quot;http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd&quot;&gt;
        
        
&lt;!--محتویات فایل hibernate.cfg.xml--&gt;


&lt;hibernate-configuration&gt;
    &lt;session-factory&gt;

        &lt;!-- JDBC Connection Settings --&gt;
        &lt;property name=&quot;connection.driver_class&quot;&gt;com.mysql.jdbc.Driver&lt;/property&gt;
        &lt;property name=&quot;connection.url&quot;&gt;jdbc:mysql://localhost:3306/hibernate?useSSL=false&lt;/property&gt;
        &lt;property name=&quot;connection.username&quot;&gt;newuser&lt;/property&gt;
        &lt;property name=&quot;connection.password&quot;&gt;password&lt;/property&gt;

        &lt;!-- Select SQL Dialect--&gt;
        &lt;property name=&quot;dialect&quot;&gt;org.hibernate.dialect.MySQL5Dialect&lt;/property&gt;
        

        &lt;!-- Hibernate Settings--&gt;
        &lt;property name=&quot;hbm2ddl.auto&quot;&gt;create&lt;/property&gt;
        &lt;property name=&quot;connection.pool_size&quot;&gt;20&lt;/property&gt;
        &lt;property name=&quot;hibernate.current_session_context_class&quot;&gt;thread&lt;/property&gt;

        &lt;property name=&quot;show_sql&quot;&gt;true&lt;/property&gt;


    &lt;/session-factory&gt;
&lt;/hibernate-configuration&gt;من دیگر اشاره‌ای به جزئیات نمی‌کنم که بطور مثال تنظیمات درون تگ hibernate-configuration قرار می‌گیرد و بعد از آن تنظیمات مورد نظر ما درون تگ session-factory است. یا نام propertyها را بیان کنم. لطفا تیزبینانه نگاه کنید و این فایل را کپی نکنید، بنویسید تا بهتر متوجه اتفاقات شوید.بخش اول، مربوط به تنظیمات اتصال به دیتابیس است. کلاس Driver و url و همچنین نام کاربری و پسورد را وارد می‌کنیم. توجه کنید که اطلاعات درایور و url برای اتصال به MySQL است، و اطلاعات نام‌کاربری و پسورد مربوط به سیستم پایگاهی من است (کپی نکنید!). قطعا متوجه شدید که اطلاعاتی را وارد می‌کنید در این بخش که همیشه هنگام کار با jdbc هم آن‌ها را استفاده می‌کردید.محتویات فایل تنظیمات بهمراه ساختار پروژه تاکنونبخش دوم، Dialect هایبرنیت است. اگر بخواهم خودمانی بگویم که اینجا چه چیز را تنظیم می‌کنیم اینطور می‌شود که به هایبرنیت می‌گوییم با چه لهجه‌ای با دیتابیس SQL ما صحبت کن. درست است که SQL استانداردی مشخص است، اما پیاده‌سازی آن در بین RDBMSها با کمی تفاوت سینتکسی همراه است. در این بخش این ابهامات را برطرف می‌کنیم (با مشخص کردن اینکه با لهجه‌ی MySQL صحبت کن).پرسش. من از اوراکل استفاده می‌کنم، چطور Dialect مربوط به آن را پیدا کنم؟پاسخ. جست‌وجو در اینترنت! لیست آنها در اینترنت هست.بخش‌های بعدی هم در رابطه با این است که هایبرنیت چطور رفتار کند. اجازه دهید از توضیح بیشتر بپرهیزیم، و به گام بعدی برویم. و بعد از آن وارد جزییات بیشتری می‌شویم.گام۳. آماده کردن کلاس‌های جاوا برای نگاشت به دیتابیسخب، عالی پیش آمدید. دیگر راه زیادی نمانده است. فقط مانده است که کلاس‌های جاوا را بنویسیم و آنها را برای نگاشت به دیتابیس آماده کنیم.اجازه دهید اینطور تصور کنیم که می‌خواهیم اطلاعات دانشجویان را در دیتابیس ذخیره کنیم. ما در دیتابیس جدول دانشجو خواهیم داشت که ستون‌های آن باید id، sname، stell و saddress باشد که به ترتیب شماره‌ی دانشجو، نام دانشجو، تلفن دانشجو و آدرس دانشجو هستند. در جاوا نیز قطعا کلاسی خواهیم داشت که این اطلاعات را میگیرد.دوستان عزیز، توجه خودتان را به آنچه از هایبرنیت و اتفاقات پیرامونش نمی‌دانید متمرکز نکنید. با من پیش بیاید و فقط به آنچه با خواندن این متن میفهمید تمرکز کنید! همه را جز به جز باز خواهیم کرد.پس در اینجا، من شروع می‌کنم کلاس Student را می‌سازم. اما این کلاس باید ویژگی‌های خاصی داشته باشد. دقیق‌تر، این کلاس باید یک POJO ساده باشد. برای نوشتن یک Plain Old Java Object چه چیزهایی الزامی است؟ تمام propertyها متدهای getter و setter داشته باشند.کلاس یک سازنده‌ی بدون آرگومان (no-args constructor) داشته باشد.پرسش. آیا باید این constructor را ساخت؟ تا جاییکه من میدانم خود کامپایلر چنین سازنده‌ای را ایجاد می‌کند.پاسخ. اگر هیچ سازنده‌ی دیگری در کلاس وجود نداشته باشد، کامپایلر چنین سازنده‌ی پیش‌فرضی را ایجاد می‌کند. اما چنان‌چه شما یک (یا چند) سازنده‌ی دیگر با آرگومان لحاظ کرده باشید، باید صراحتا خودتان یک سازنده‌ی بدون آرگومان ایجاد کنید.کلاس داشنجو باید مشابه زیر شده باشد:package entities;

public class Student {
    
    private int id;
    private String name;
    private String tell;
    private String address;

    
    public Student() {} // non-arg constructor
    
    // Setters &amp; Getters
    
}من مشخصه‌های تلفن و آدرس را نیز از نوع String در نظر گرفتم (برای سهولت کار). و کاملا مشخص است که از آوردن متدهای setter &amp; getter پرهیز شده است. شما برای خودتان باید بنویسید. کمی بعد عکسی از این کلاس خواهم گذاشت تا ابهامات احتمالی برطرف شود.خب، سوالی اساسی اینجا مطرح می‌شود. چطور باید به هایبرنیت بفهمانم که این کلاس باید به جدولی بنام student در دیتابیس تبدیل شود، و چطور اسم مشخصه‌ی name را sname بگذارد و چطور به دیتابیس بگوید که فیلد id را کلیداصلی (primary key) در نظر بگیرد؟! باید راهی باشد تا نقشه‌ی نگاشت را به هایبرنیت گفت، تا به کمک آن نقشه هایبرنیت عملیات نگاشت را انجام دهد.پیش‌تر ها چنین نقشه‌ای را در یک فایل دیگر xml قرار می‌دادند و هایبرنیت به کمک آن فایل میفهمید که با کلاس Student چطور باید رفتار کند. اینکه آیا اصلا این کلاس را باید به جدولی تبدیل کند؟ اگر بله، به چه نامی؟ اینکه چطور با فیلدهای آن رفتار کند، کلید اصلی کدام فیلد است، اسم فیلدها در دیتابیس چگونه باشد، و چه محدودیت‌هایی برای آن بگذارد و... را در آن فایل xml به هایبرنیت معرفی می‌کردیم.امروزه چکار می‌کنند؟ امروزه عمدتا از راه آسان‌تری استفاده می‌شود. از Annotationها استفاده می‌کنیم. با استفاده از Annotationها می‌توانیم تمام آن اطلاعات را خیلی آسان‌تر و شفاف‌تر به هایبرنیت بدهیم. پس وقت آن است که شروع به معرفی Annotationهای نگاشت کنیم.پرسش. Annotation چی هست؟پاسخ. Annotation همانطور که از ترجمه‌ی لغوی آن پیداست یکجور حاشیه نویسی است. می‌توان آن را به چشم متادیتا دید (اطلاعاتی اضافه). فریمورکی همچون هایبرنیت از این اطلاعات اضافه برای چگونگی نگاشت استفاده می‌کنند. استفاده از Annotationها بسیار رایج است، بخصوص در استفاده از فریمورک‌هایی نظیر Spring یا هایبرنیت. حتما در Java Core هم از Annotationهایی نظیر @Override استفاده کرده‌اید.اولین Annotationی که باید استفاده کنیم تا به هایبرنیت بگوید این کلاس باید تبدیل به یک موجودیت در دیتابیس شود، @Entity است. این Annotation به هایبرنیت می‌گوید که این کلاس را تبدیل به یک جدول کن (به محاوره‌ترین شکل ممکن گفتم!).تصویر زیر حالت کامل شده است، مشاهده کنید و به تمام Annotationهای آن توجه کنید.کلاس Studentخیلی خلاصه ادامه می‌دهم و بعد از گام۴ به آن برخواهم گشت و جز به جز توضیح خواهم داد.در خط ۶ به کمک @Table و شناسه‌ی name به هایبرنیت گفتم که می‌خواهم چه نامی برای این کلاس در دیتابیس درنظر بگیرد. @Table اختیاری است، چنانچه استفاده نکنید هایبرنیت نام کلاس را بعنوان اسم جدول قرار می‌دهد (که در این مثال هیچ فرقی ندارد!).در خط ۹ به هایبرنیت گفتم که فیلد id کلید اصلی من در جدول می‌باشد (با کمک @Id) و با @GeneratedValue هم وظیفه‌ی یکتا بودن کلید را به هایبرنیت سپردم. به این معنا که دیگر خود هایبرنیت وظیفه‌ی تولید id را به گردن دارد. (مشابه Auto Increment در دیتابیس).در خط‌های بعد از @Column استفاده کردم. استفاده از این Annotation اختیاری است. به این معنا که در نبودن آن هایبرنیت اطلاعات پیش‌فرض را قرار می‌دهد. بعنوان مثال در مورد فیلد address هیچ Annotationی لحاظ نشده است، به این خاطر هایبرنیت نام ستون را دقیقا با نام فیلد قرار می‌دهد. اما در مورد فیلد name به هایبرنیت گفته شده است که نام این ستون را sname قرار بده.نکته‌ی بسیار مهم در رابطه با این Annotationها این است که همه‌ی آنها از پکیج javax.persistence می‌باشد. بعبارتی این‌ها Annotationهای JPA هستند و نه Hibernate. البته هایبرنیت هم مشابه آنها را دارد، اما خود هایبرنیت توصیه می‌کند که از Annotationهای پکیج JPA استفاده بشود.شاید برایتان جالب باشد که هایبرنیت قدمت بیشتری از JPA دارد، بعبارتی ابتدا هایبرنیت متولد شد، با بخت و اقبال مواجه شد، به همین خاطر استانداردی (JPA) برای آن در نظر گرفتند.پرسش. من همچنان متوجه @Id نشدم. این Annotation صرفا کلیداصلی را مشخص می‌کند؟پاسخ. بله، همین است. چیز پیچیده‌ای نیست.پرسش. چطور بفهمم @GeneratedValue چه چیز تولید می‌کند؟ میتوانم بر آن مدیریت داشته باشم؟پاسخ. بله، میتوان مدیریت کرد. ولی بطور پیشفرض چند استراتژی از پیش تعیین شده هم برای استفاده گذاشته‌اند. پاسخ دقیق به این سوال را در این قسمت صلاح نمی‌دانم، فقط بدانید که بله می‌شود مدیریت کرد.پرسش. آیا می‌توانم فیلدی را کلیداصلی در نظر بگیرم ولی @GeneratedValue را استفاده نکنم؟پاسخ. بله می‌شود. آنگاه خودتان باید یکتایی مقدار را تضمین کنید.پرسش. اگر بخواهم چند فیلد را باهم بعنوان کلید نظر بگیرم، باید برای هرکدام از آن فیلد از @Id استفاده کنم؟پاسخ. خیر، ابدا. این موضوع را در قسمت دوم بخش کلیداصلی مرکب توضیح خواهم داد، تا آن زمان صبور باشید.خب اجازه دهید تمام کد را هم به اشتراک بگذارم و به سراغ گام بعد برویم.package entities;

import javax.persistence.*;

@Entity
@Table(name = &quot;student&quot;)
public class Student {

    @Id @GeneratedValue
    private int id;
    @Column(name = &quot;sname&quot;)
    private String name;
    @Column(name = &quot;stell&quot;)
    private String tell;
    private String address;


    public Student() {} // non-arg constructor

    public Student(String name, String tell, String address) {
        this.name = name;
        this.tell = tell;
        this.address = address;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Student student = (Student) o;

        return id == student.id;
    }

    @Override
    public int hashCode() {
        return id;
    }

    @Override
    public String toString() {
        return &quot;Student{&quot; +
                &quot;id=&quot; + id +
                &quot;, name=&#039;&quot; + name + &#039;\&#039;&#039; +
                &quot;, tell=&#039;&quot; + tell + &#039;\&#039;&#039; +
                &quot;, address=&#039;&quot; + address + &#039;\&#039;&#039; +
                &#039;}&#039;;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getTell() {
        return tell;
    }

    public void setTell(String tell) {
        this.tell = tell;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}پرسش. چرا متدهای hashCode و equals هم ایجاد شده است؟پاسخ. این متدها به هایبرنیت در انجام تضمین یگانگی فیلد id کمک می‌کند. همانطور که ملاحظه می‌کنید متد equals فقط برای فیلد id ایجاد شده است. البته این کار الزامی نیست. یکجور سفت کاری است!پرسش. اجازه دهید! من دارم گیج می‌شوم. حجم مطالب زیاد شده است و شما پرحرفی زیادی میکنید. باعث شده است من گم کنم!پاسخ. حق دارید، ولی نگران نباشید. تنها یک گام دیگر تا معجزه باقی مانده است. کار زیادی تا الان انجام ندادیم، فقط مجبور به پرحرفی بودیم که موجب نگرانی شما شده است.تاکنون ما کتابخانه‌های موردنیاز را اضافه کردیم، یک فایل کانفیگ ساختیم و اطلاعات ارتباط با دیتابیس را وارد آن کردیم، و در نهایت یک کلاس جاوای خود را به کمک Annotationها به Entity تبدیل کردیم. و حالا هم میرویم که تست انجام دهیم. به همین سادگی. همراه باشید!گام۴. اجرای عملیاتهای پایگاه‌داده‌ایتست کردن و گام آخرهرآنچه که برای آزمودن هایبرنیت می‌بایست انجام دهیم در تصویر بالا مشخص است. در این تصویر من ابتدا یک شی از کلاس Student ایجاد کرده‌ام و سپس آن را درون دیتابیس ذخیره (save) کرده‌ام. خروجی را میخواهید در دیتابیس مشاهده کنید؟ عکس زیر را ملاحظه کنید.خروجی جدول دانشجو دقیقا همان است که انتظار داشتیم. دوستان من خسته نباشید. نفسی تازه کنید، اکنون دریافتید که هایبرنیت چطور کار می‌کند. اما هیچ توضیحی راجع به این کلاس‌ها و آبجکت‌های عجیب و غریب که در فایل Test است ندادیم. محتویات کلاس Test را مشاهده کنید:package entities;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class Test {

    public static void main(String[] args) {

        SessionFactory sessionFactory = new Configuration().configure()
                .addAnnotatedClass(Student.class)
                .buildSessionFactory();

        Session session = sessionFactory.getCurrentSession();

        Student student = new Student(&quot;Mohamad&quot;, &quot;09121112233&quot;, &quot;Tehran&quot;);

        session.beginTransaction();

        session.save(student);

        session.getTransaction().commit();

        session.close();
        sessionFactory.close();
    }
}کلاس SessionFactory فایل تنظیمات را می‌خواند (به کمک کلاس Configuration) و یک آبجکت سنگین (به این خاطر که تنها یکبار ساخته می‌شود) ایجاد می‌کند. در خط ۱۴ من به تنظیمات این را اضافه کردم که به کلاس Student نگاه کند. این کار باید صورت بگیرد، در غیر این صورت هایبرنیت این کلاس را برای نگاشت درنظر نمی‌گیرد.کلاس Session ارتباط jdbc را Wrap کرده است. کلاس اصلی برای ذخیره و بازیابی اطلاعات از پایگاه داده است. شی این کلاس از کلاس SessionFactory گرفته می‌شود.سپس یک شی از کلاس Student ایجاد کردیم (بنام student)، و در نهایت تراکنشی را به کمک متد   beginTransaction از کلاس Session شروع کردیم و پس از آن به کمک متد save از کلاس Session مقدار student را درون دیتابیس ذخیره کردیم. و در آخر تراکنش را commit کردیم.پرسش. متوجه آنچه شما گفتید شدم! اما سوالات فراوانی دارم.پاسخ. کاملا طبیعی است، بخشی از آن سوالات را می‌توانم حدس بزنم چه‌ها هستند. توضیح خواهم داد. اما در قسمت بعد!باید همین اتفاقی که اینجا رخ داد را خیلی بیشتر بسط داد.لطفا نظر خودتون رو کامنت کنید، آیا توانستید از این مطلب استفاده کنید؟حمایت معنوی از گروه داده‌کاوی دایکه</description>
                <category>نشریه دایکه</category>
                <author>محمد عباسی</author>
                <pubDate>Wed, 24 Apr 2019 16:04:38 +0430</pubDate>
            </item>
            </channel>
</rss>