ביקורת עם JPA, Hibernate ו- Spring Data JPA

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

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

נדגים שלוש גישות להכנסת ביקורת ליישום. ראשית, ניישם אותו באמצעות JPA רגיל. לאחר מכן, נבחן שתי הרחבות JPA המספקות פונקציונליות ביקורת משלהן: אחת שמספקת Hibernate, אחרת על ידי Spring Data.

להלן ישויות הקשורות לדוגמא, בָּר ו פו, שישמש בדוגמה זו:

2. ביקורת עם JPA

JPA אינו מכיל במפורש ממשק API לביקורת, אך ניתן להשיג את הפונקציונליות באמצעות אירועי מחזור החיים של הישות.

2.1. @PrePersist,@ PreUpdate ו @PreRemove

ב- JPA יֵשׁוּת בכיתה, ניתן לציין שיטה כהתקשרות חוזרת שתופעל במהלך אירוע מסוים של מחזור חיים של ישות מסוימת. מכיוון שאנחנו מעוניינים בשיחות חוזרות שמבוצעות לפני פעולות ה- DML המתאימות, יש @ PrePersist, @ PreUpdate ו @PreRemove הערות להתקשרות חוזרות זמינות למטרות שלנו:

בר @Entity public class {@PrePersist public void onPrePersist () {...} @PreUpdate public public onPreUpdate () {...} @PreRemove Public spid onPreRemove () {...}}

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

היה מודע לכך שה- @גִרְסָה ביאור ב- JPA אינו קשור בהחלט לנושא שלנו - זה קשור לנעילה אופטימית יותר מאשר לנתוני ביקורת.

2.2. יישום שיטות ההתקשרות

עם זאת, קיימת מגבלה משמעותית בגישה זו. כאמור במפרט JPA 2 (JSR 317):

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

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

סרגל מחלקה ציבורית @Entity {// ... @Column (name = "operation") פעולת מחרוזת פרטית; @Column (name = "timestamp") חותמת זמן פרטית ארוכה; // ... // סטרים סטנדרטיים וגטרים למאפיינים החדשים // ... @PrePersist public void onPrePersist () {audit ("INSERT"); } @PreUpdate חלל ציבורי onPreUpdate () {ביקורת ("עדכן"); } @PreRemove חלל ציבורי onPreRemove () {ביקורת ("מחק"); } ביקורת חלל פרטית (פעולת מחרוזת) {setOperation (פעולה); setTimestamp ((תאריך חדש ()). getTime ()); }}

אם אתה צריך להוסיף ביקורת כזו למספר שיעורים, אתה יכול להשתמש בה @EntityListeners לרכז את הקוד. לדוגמה:

@EntityListeners (AuditListener.class) @ בר בכיתה ציבורית @Entity {...}
AuditListener בכיתה ציבורית {@PrePersist @PreUpdate @PreRemove ריק ריק לפני AnyOperation (אובייקט אובייקט) {...}}

3. מקלטים במצב שינה

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

3.1. התחל בעבודה עם Envers

כדי להגדיר את Envers, עליך להוסיף את ה- שינה תרדמת JAR אל מסלול הכיתה שלך:

 org.hibernate hibernate-envers $ {hibernate.version} 

ואז פשוט להוסיף את @Audited ביאור או על @יֵשׁוּת (לביקורת על כל הישות) או על ספציפי @טור(אם אתה צריך לבקר מאפיינים ספציפיים בלבד):

@Entity @ בר כיתה ציבורית מבוקר {...}

ציין זאת בָּר מקיים קשר אחד לרבים עם פו. במקרה זה, עלינו לבצע ביקורת פו וכן על ידי הוספה @Audited עַל פו או להגדיר @NotAudited על רכוש היחסים ב בָּר:

@OneToMany (mappedBy = "bar") @NotAudited הגדר פרטי fooSet;

3.2. יצירת טבלאות יומן ביקורת

ישנן מספר דרכים ליצור טבלאות ביקורת:

  • מַעֲרֶכֶת hibernate.hbm2ddl.auto ל לִיצוֹר, ליצור-ירידה אוֹ עדכוןכך ש- Envers יוכלו ליצור אותם באופן אוטומטי
  • השתמש ב- org.hibernate.tool.EnversSchemaGenerator לייצא את סכמת מסד הנתונים המלאה באופן פרוגרמטי
  • השתמש במשימת נמלים כדי ליצור הצהרות DDL מתאימות
  • השתמש בתוסף Maven ליצירת סכימת מסד נתונים מהמיפויי שלך (כגון Juplo) כדי לייצא את סכימת Envers (עובד עם Hibernate 4 ומעלה)

נלך במסלול הראשון, מכיוון שהוא הכי פשוט, אבל היה מודע לשימוש hibernate.hbm2ddl.auto אינו בטוח בייצור.

במקרה שלנו, בר_אוד ו foo_AUD (אם הגדרת פו כפי ש @Audited כמו כן) יש ליצור טבלאות באופן אוטומטי. טבלאות הביקורת מעתיקות את כל השדות המבוקרים מטבלת הישות עם שני שדות, REVTYPE (הערכים הם: "0" להוספת, "1" לעדכון, "2" להסרת ישות) ו- לְהַאִיץ.

מלבד אלה, שולחן נוסף בשם REVINFO ייווצר כברירת מחדל, הוא כולל שני שדות חשובים, לְהַאִיץ ו REVTSTMP ומתעד את חותמת הזמן של כל תיקון. וכפי שאתה יכול לנחש, bar_AUD.REV ו foo_AUD.REV הם למעשה מפתחות זרים ל REVINFO.REV.

3.3. קביעת תצורה של Envers

באפשרותך להגדיר תצורה של מאפייני Envers בדיוק כמו כל מאפיין שינה אחר.

לדוגמא, בואו לשנות את סיומת טבלת הביקורת (אשר ברירת המחדל היא "_אוד") ל "_יומן ביקורת". כך מגדירים את ערך הנכס המתאים org.hibernate.envers.audit_table_suffix:

מאפיינים hibernateProperties = מאפיינים חדשים (); hibernateProperties.setProperty ("org.hibernate.envers.audit_table_suffix", "_AUDIT_LOG"); sessionFactory.setHibernateProperties (hibernateProperties);

ניתן למצוא רשימה מלאה של נכסים זמינים בתיעוד Envers.

3.4. גישה להיסטוריית ישויות

באפשרותך לבצע שאילתות על נתונים היסטוריים באופן הדומה לשאילתת נתונים באמצעות ממשק ה- API של קריטריונים של מצב שינה. ניתן לגשת להיסטוריית הביקורת של ישות באמצעות ה- AuditReader ממשק, שניתן להשיג באמצעות פתוח EntityManager אוֹ מוֹשָׁב דרך ה- AuditReaderFactory:

קורא AuditReader = AuditReaderFactory.get (הפעלה);

Envers מספק AuditQueryCreator (הוחזר על ידי AuditReader.createQuery ()) על מנת ליצור שאילתות ספציפיות לביקורת. השורה הבאה תחזיר את כולם בָּר מקרים ששונו במהדורה מספר 2 (איפה bar_AUDIT_LOG.REV = 2):

שאילתת AuditQuery = reader.createQuery () .forEntitiesAtRevision (Bar.class, 2)

כך תשאול בָּרהתיקונים, כלומר זה יביא לקבלת רשימה של כולם בָּר מקרים בכל מדינותיהם שעברו ביקורת:

שאילתת AuditQuery = reader.createQuery (). ForRevisionsOfEntity (Bar.class, true, true);

אם הפרמטר השני אינו נכון התוצאה מצטרפת ל- REVINFO אחרת, רק מופעי ישויות מוחזרים. הפרמטר האחרון מציין אם להחזיר שנמחק בָּר מקרים.

אז אתה יכול לציין אילוצים באמצעות AuditEntity כיתת מפעל:

query.addOrder (AuditEntity.revisionNumber (). desc ());

4. נתוני אביב JPA

Spring Data JPA היא מסגרת המרחיבה את JPA על ידי הוספת שכבת הפשטה נוספת על גבי ספק ה- JPA. שכבה זו מאפשרת תמיכה ביצירת מאגרי JPA על ידי הרחבת ממשקי מאגר JPA של Spring.

לענייננו תוכלו להאריך מאגר Crud, הממשק לפעולות CRUD כלליות. ברגע שיצרת והזרקת את המאגר שלך לרכיב אחר, Spring Data יספק את היישום באופן אוטומטי ואתה מוכן להוסיף פונקציונליות ביקורת.

4.1. הפעלת ביקורת JPA

כדי להתחיל, אנו רוצים לאפשר ביקורת באמצעות תצורת ביאור. על מנת לעשות זאת, פשוט הוסף @EnableJpaAuditing על שלך @תְצוּרָה מעמד:

@Configuration @EnableTransactionManagement @EnableJpaRepositories @EnableJpaAuditing class public PersistenceConfig {...}

4.2. הוספת מאזין החזרת שיחות של האביב

כידוע, JPA מספקת את @EntityListeners ביאור לציין שיעורי מאזינים להתקשרות חוזרת. Spring Data מספק מחלקת מאזינים לישות JPA משלה: AuditingEntityListener. אז בואו נציין את המאזין ל- בָּר יֵשׁוּת:

@Entity @EntityListeners (AuditingEntityListener.class) בר כיתה ציבורית {...}

כעת מידע הביקורת יתפוס על ידי המאזין בהתמדה ועדכון בָּר יֵשׁוּת.

4.3. מעקב אחר תאריכים שנוצרו ושונו לאחרונה

לאחר מכן נוסיף שני מאפיינים חדשים לאחסון התאריכים שנוצרו ושונו לאחרונה בָּר יֵשׁוּת. המאפיינים מסומנים על ידי @תאריך יצירה ו @LastModifiedDate הערות בהתאם, וערכיהם נקבעים באופן אוטומטי:

@Entity @EntityListeners (AuditingEntityListener.class) סרגל כיתה ציבורי {// ... @Column (name = "created_date", nullable = false, updatable = false) @CreatedDate פרטי long createdDate; @Column (name = "modified_date") @LastModifiedDate פרטי זמן ארוך שונה; // ...}

באופן כללי, היית מעביר את המאפיינים למחלקת בסיס (מסומנת על ידי @MappedSuperClass) שיוארך על ידי כל הגופים המבוקרים שלך. בדוגמה שלנו, אנו מוסיפים אותם ישירות אל בָּר למען הפשטות.

4.4. ביקורת מחבר השינויים באבטחת האביב

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

@Entity @EntityListeners (AuditingEntityListener.class) סרגל מחלקה ציבורי {// ... @Column (name = "created_by") @CreatedBy מחרוזת פרטית createdBy; @Column (name = "modified_by") @ LastModifiedBy מחרוזת פרטית modifiedBy; // ...}

העמודות עם הערות עם @נוצר על ידי ו @LastModifiedBy מאוכלסים בשם המנהל שיצר או שינה לאחרונה את הישות. המידע נמשך אבטחה הקשרשל אימות למשל. אם ברצונך להתאים אישית ערכים המוגדרים לשדות המסומנים, תוכל ליישם AuditorAware מִמְשָׁק:

מחלקה ציבורית AuditorAwareImpl מיישמת את AuditorAware {@Override Public String getCurrentAuditor () {// ההיגיון המותאם אישית שלך}}

על מנת להגדיר את האפליקציה לשימוש AuditorAwareImpl לחפש את המנהל הנוכחי, להכריז שעועית של AuditorAware סוג מאותחל עם מופע של AuditorAwareImpl וציין את שם השעועית כ- auditorAwareRef ערך הפרמטר ב- @EnableJpaAuditing:

@EnableJpaAuditing (auditorAwareRef = "auditorProvider") מעמד ציבורי PersistenceConfig {// ... @Bean AuditorAware auditorProvider () {להחזיר AuditorAwareImpl חדש (); } // ...}

5. מסקנה

שקלנו שלוש גישות ליישום פונקציונליות ביקורת:

  • גישת ה- JPA הטהורה היא הבסיסית ביותר ומורכבת משיחות חוזרות במחזור החיים. עם זאת, מותר לשנות רק את המצב שאינו קשר של ישות. זה הופך את @PreRemove התקשרות חזרה חסרת תועלת למטרות שלנו, מכיוון שכל הגדרות שביצעת בשיטה יימחקו ואז יחד עם הישות.
  • Envers הוא מודול ביקורת בוגר שמספק Hibernate. זה ניתן להגדרה גבוהה וחסר את הפגמים ביישום ה- JPA הטהור. לפיכך, היא מאפשרת לנו לבקר את פעולת המחיקה, מכיוון שהיא נכנסת לטבלאות שאינן הטבלה של הישות.
  • גישת ה- Spring Data JPA מופשטת בעבודה עם התקשרות חוזרת של JPA ומספקת הערות שימושיות עבור מאפייני ביקורת. זה מוכן גם לשילוב עם Spring Security. החיסרון הוא שהוא יורש את אותם פגמים בגישת ה- JPA, כך שלא ניתן לבקר את פעולת המחיקה.

הדוגמאות למאמר זה זמינות במאגר GitHub.


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