פשט את ה- DAO באמצעות Spring ו- Java Generics

1. סקירה כללית

מאמר זה יתמקד ב לפשט את שכבת DAO על ידי שימוש באובייקט גישה אחד לנתונים שנוצר לכל הגופים במערכת, מה שיוביל לגישה אלגנטית לנתונים, ללא עומס מיותר או מילוליות מיותרת.

אנו נבנה על מחלקת ה- DAO המופשטת שראינו במאמר הקודם שלנו בנושא Spring and Hibernate, ונוסיף תמיכה גנרית.

2. מערכות החורף וה- JPA DAO

ברוב קודני הייצור יש שכבת DAO כלשהי. בדרך כלל, היישום נע בין מספר שיעורים ללא מחלקת בסיס מופשטת למחלקה כלשהי. עם זאת, דבר אחד הוא עקבי - יש תמיד יותר מאחד. סביר להניח שיש קשר אחד לאחד בין ה- DAO לבין הגופים במערכת.

כמו כן, בהתאם לרמת הגנריות המעורבות, היישומים בפועל יכולים להשתנות מקוד כפול מאוד לכמעט ריק, כאשר עיקר הלוגיקה מקובצת בכיתה מופשטת בסיסית.

בדרך כלל ניתן להחליף יישומים מרובים אלה ב- DAO פרמטרי בודד. אנו יכולים ליישם זאת כך ששום פונקציונליות לא תאבד על ידי ניצול מלא של בטיחות הסוג שמספקת Java Generics.

נציג שתי מימושים של הרעיון הבא, האחת לשכבת התמדה ממוקדת במצב שינה, והשנייה מתמקדת ב- JPA. יישומים אלה בשום אופן לא הושלמו, אך אנו יכולים להוסיף בקלות שיטות נוספות נוספות לגישה לנתונים.

2.1. ה- DAO ה- Hibernate Hibernate

בואו נסתכל במהירות על ה- תקציר HibernateDao מעמד:

שיעור מופשט ציבורי AbstractHibernateDao {clazz Class private; @Autowired SessionFactory sessionFactory; public void setClazz (Class clazzToSet) {this.clazz = clazzToSet; } ציבורי T findOne (id ארוך) {return (T) getCurrentSession (). get (clazz, id); } רשימה ברשימה ציבורית findAll () {return getCurrentSession (). createQuery ("from" + clazz.getName ()). list (); } צורה ציבורית T (ישות T) {getCurrentSession (). saveOrUpdate (ישות); ישות החזרה; } עדכון T ציבורי (ישות T) {החזר (T) getCurrentSession (). מיזוג (ישות); מחיקה בטלנית ציבורית (ישות T) {getCurrentSession (). מחיקה (ישות); } public void deleteById (long entityId) {T entity = findOne (entityId); מחק (ישות); } מושב מוגן getCurrentSession () {return sessionFactory.getCurrentSession (); }}

זהו מחלקה מופשטת עם מספר שיטות גישה לנתונים, המשתמשת ב- SessionFactory על מניפולציות על ישויות.

2.2. ה- DAO ה- Hibernate Generic

כעת, כשיש לנו את מעמד ה- DAO המופשט, נוכל להאריך אותו רק פעם אחת. היישום הגנרי של DAO יהפוך ליישום היחיד אנחנו צריכים:

@Repository @Scope (BeanDefinition.SCOPE_PROTOTYPE) מעמד ציבורי GenericHibernateDao מרחיב תקציר HibernateDao מיישם IGenericDao {//}

ראשון, שים לב כי היישום הגנרי הוא בעצמו פרמטרי, המאפשר ללקוח לבחור את הפרמטר הנכון על בסיס כל מקרה לגופו. פירוש הדבר שהלקוחות מקבלים את כל היתרונות של בטיחות סוג מבלי שיהיה צורך ליצור חפצים מרובים עבור כל ישות.

שנית, שימו לב היקף האב-טיפוס של יישום DAO כללי זה. השימוש בהיקף זה פירושו כי מיכל האביב ייצור מופע חדש של ה- DAO בכל פעם שהוא מתבקש (כולל בחיווט אוטומטי). זה יאפשר לשירות להשתמש במספר DAOs עם פרמטרים שונים עבור ישויות שונות, לפי הצורך.

הסיבה שההיקף הזה כל כך חשוב נובעת מהאופן שבו אביב מסמל שעועית במיכל. השארת ה- DAO הגנרי ללא היקף פירושה שימוש היקף ברירת המחדל של יחיד, מה שיוביל למופע יחיד של ה- DAO המתגורר במיכל. ברור שזה יהיה מגביל במידה רבה לכל תרחיש מורכב יותר.

ה IGenericDao הוא פשוט ממשק לכל שיטות ה- DAO כדי שנוכל להזריק את היישום הדרוש לנו:

ממשק ציבורי IGenericDao {T findOne (מזהה ארוך סופי); רשימה findAll (); בטל יצירת (ישות T סופית); עדכון T (ישות T סופית); מחיקה בטלה (ישות T סופית); בטל deleteById (entityId ארוך סופי); }

2.3. ה- JPO DAO המופשט

ה תקציר JpaDao דומה מאוד ל תקציר HibernateDao:

שיעור מופשט ציבורי AbstractJpaDao {clazz Class private; @PersistenceContext EntityManager entityManager; public void setClazz (Class clazzToSet) {this.clazz = clazzToSet; } T FindOne ציבורי (מזהה ארוך) {return entityManager.find (clazz, id); } רשימה ציבורית findAll () {return entityManager.createQuery ("from" + clazz.getName ()) .getResultList (); } שמירת חלל ציבורי (ישות T) {entityManager.persist (ישות); } עדכון חלל ציבורי (ישות T) {entityManager.merge (ישות); } מחיקת ריק ריק (ישות T) {entityManager.remove (ישות); } בטל ציבורי deleteById (Long entityId) {T entity = getById (entityId); מחק (ישות); }}

בדומה ליישום ה- DAO ה- Hibernate, אנו משתמשים ישירות ב- API של Persistence Java, מבלי להסתמך על האביב שהוצא משימוש כעת. JpaTemplate.

2.4. ה- JPO DAO הגנרי

בדומה ליישום שינה, גם אובייקט JPA Data Access הוא פשוט:

@Repository @Scope (BeanDefinition.SCOPE_PROTOTYPE) מחלקה ציבורית GenericJpaDao מרחיב את AbstractJpaDao מיישמת IGenericDao {//}

3. הזרקת DAO זה

כעת יש לנו ממשק DAO אחד שנוכל להזריק. עלינו גם לציין את מעמד:

מחלקת @ שירות FooService מיישמת את IFooService {IGenericDao dao; @Autowired חלל ציבורי setDao (IGenericDao daoToSet) {dao = daoToSet; dao.setClazz (Foo.class); } // ...}

אביב מחבר אוטומטית את מופע ה- DAO באמצעות הזרקת סטר כך שניתן להתאים אישית את היישום עם מעמד לְהִתְנַגֵד. לאחר נקודה זו, ה- DAO פרמטריז לחלוטין ומוכן לשימוש על ידי השירות.

יש כמובן דרכים אחרות בהן ניתן לציין את הכיתה עבור ה- DAO - באמצעות השתקפות, או אפילו ב- XML. העדפתי היא כלפי פיתרון פשוט יותר זה בגלל הקריאות והשקיפות המשופרים בהשוואה לשימוש בבבואה.

4. מסקנה

מאמר זה דן ב פשטה של ​​שכבת גישה לנתונים על ידי מתן יישום יחיד לשימוש חוזר של DAO כללי. הראינו את ההטמעה בסביבת שינה וגם בסביבת JPA. התוצאה היא שכבת התמדה יעילה, ללא עומס מיותר.

לקבלת מבוא שלב אחר שלב אודות הגדרת הקשר האביב באמצעות תצורה מבוססת Java ופום Maven הבסיסי לפרויקט, עיין במאמר זה.

לבסוף, ניתן למצוא את הקוד עבור מאמר זה בפרויקט GitHub.


$config[zx-auto] not found$config[zx-overlay] not found