JavaRush /בלוג Java /Random-HE /JPA: הצגת הטכנולוגיה
Viacheslav
רָמָה

JPA: הצגת הטכנולוגיה

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

מבוא

כפי שאנו יודעים, אחת המשימות העיקריות של תוכניות היא אחסון ועיבוד נתונים. בימים הטובים, אנשים פשוט אחסנו נתונים בקבצים. אבל ברגע שיש צורך בגישת קריאה ועריכה בו זמנית, כאשר יש עומס (כלומר, מספר בקשות מגיעות בו זמנית), אחסון נתונים פשוט בקבצים הופך לבעיה. למידע נוסף על אילו בעיות פותרים מסדי נתונים וכיצד, אני ממליץ לך לקרוא את המאמר " כיצד בנויים מסדי נתונים ." משמעות הדבר היא שאנו מחליטים לאחסן את הנתונים שלנו במסד נתונים. מזה זמן רב, Java הצליחה לעבוד עם מסדי נתונים באמצעות ה-API של JDBC (The Java Database Connectivity). אתה יכול לקרוא עוד על JDBC כאן: " JDBC או איפה הכל מתחיל ." אבל הזמן חלף ומפתחים בכל פעם התמודדו עם הצורך לכתוב את אותו סוג וקוד "תחזוקה" מיותר (מה שנקרא קוד Boilerplate) עבור פעולות טריוויאליות של שמירת אובייקטי Java במסד הנתונים ולהיפך, יצירת אובייקטי Java באמצעות נתונים מה- מאגר מידע. ואז, כדי לפתור את הבעיות האלה, נולד מושג כמו ORM. ORM - מיפוי יחס אובייקט או מתורגם לרוסית מיפוי יחס אובייקטיבי. זוהי טכנולוגיית תכנות המקשרת בין מסדי נתונים למושגים של שפות תכנות מונחה עצמים. כדי לפשט, ORM הוא החיבור בין אובייקטי ג'אווה לרשומות במסד נתונים: JPA: מבוא לטכנולוגיה - 2ORM הוא בעצם התפיסה שאובייקט ג'אווה יכול להיות מיוצג כנתונים במסד נתונים (ולהיפך). הוא התגלם בצורה של מפרט JPA - Java Persistence API. המפרט הוא כבר תיאור של Java API שמבטא את המושג הזה. המפרט אומר לנו אילו כלים יש לספק לנו (כלומר, באילו ממשקים אנו יכולים לעבוד) על מנת לעבוד על פי תפיסת ה-ORM. ואיך להשתמש בכספים האלה. המפרט אינו מתאר את יישום הכלים. זה מאפשר להשתמש ביישומים שונים עבור מפרט אחד. אתה יכול לפשט את זה ולומר שמפרט הוא תיאור של ה-API. ניתן למצוא את הטקסט של מפרט JPA באתר אורקל: " JSR 338: JavaTM Persistence API ". לכן, על מנת להשתמש ב-JPA, אנו זקוקים למימוש כלשהו שאיתו נשתמש בטכנולוגיה. יישומי JPA נקראים גם ספקי JPA. אחד המימושים הבולטים ביותר של JPA הוא Hibernate . לכן אני מציע לשקול את זה.
JPA: מבוא לטכנולוגיה - 3

יצירת פרויקט

מכיוון ש-JPA עוסק ב-Java, נצטרך פרויקט Java. נוכל ליצור באופן ידני את מבנה הספריות בעצמנו ולהוסיף את הספריות הדרושות בעצמנו. אבל הרבה יותר נוח ונכון להשתמש במערכות לאוטומציה של הרכבה של פרויקטים (כלומר, בעצם, זו רק תוכנה שתנהל עבורנו את הרכבת הפרויקטים. צור ספריות, הוסף את הספריות הדרושות ל-classpath וכו' .). מערכת אחת כזו היא Gradle. אתה יכול לקרוא עוד על Gradle כאן: " מבוא קצר עם Gradle ". כידוע, פונקציונליות Gradle (כלומר הדברים שהיא יכולה לעשות) מיושמת באמצעות תוספים שונים של Gradle. בואו נשתמש ב- Gradle ובתוסף " Gradle Build Init Plugin ". בוא נריץ את הפקודה:

gradle init --type java-application
Gradle תעשה עבורנו את מבנה הספריות הדרוש ותיצור תיאור הצהרתי בסיסי של הפרויקט בסקריפט ה-build build.gradle. אז יש לנו אפליקציה. אנחנו צריכים לחשוב מה אנחנו רוצים לתאר או לדגמן עם האפליקציה שלנו. בואו נשתמש בכלי מידול כלשהו, ​​למשל: app.quickdatabasediagrams.com JPA: מבוא לטכנולוגיה - 4 כאן כדאי לומר שמה שתיארנו הוא "מודל הדומיין" שלנו. תחום הוא "תחום נושא". באופן כללי, תחום הוא "החזקה" בלטינית. בימי הביניים, זה היה השם שניתן לאזורים שהיו בבעלות מלכים או אדונים פיאודליים. ובצרפתית זה הפך למילה "דומיין", שמתורגמת בפשטות ל"אזור". כך תיארנו את "מודל התחום" שלנו = "מודל הנושא". כל מרכיב במודל הזה הוא סוג של "מהות", משהו מהחיים האמיתיים. במקרה שלנו, מדובר בישויות: קטגוריה ( Category), נושא ( Topic). בואו ניצור חבילה נפרדת עבור הישויות, למשל עם מודל השם. ובואו נוסיף שם מחלקות Java שמתארות ישויות. בקוד Java, ישויות כאלה הן POJO רגיל , שעשוי להיראות כך:
public class Category {
    private Long id;
    private String title;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}
בואו נעתיק את תוכן הכיתה וניצור מחלקה באנלוגיה Topic. הוא יהיה שונה רק במה שהוא יודע על הקטגוריה שאליה הוא שייך. לכן, בואו נוסיף Topicלכיתה שדה קטגוריה ושיטות לעבודה איתו:
private Category category;

public Category getCategory() {
	return category;
}

public void setCategory(Category category) {
	this.category = category;
}
כעת יש לנו יישום Java שיש לו מודל תחום משלו. עכשיו הגיע הזמן להתחיל להתחבר לפרויקט JPA.
JPA: מבוא לטכנולוגיה - 5

הוספת JPA

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

dependencies {
	implementation 'com.h2database:h2:1.4.199'
עכשיו יש לנו מסד נתונים. כעת נוכל להוסיף שכבה לאפליקציה שלנו שאחראית למיפוי אובייקטי Java שלנו למושגי מסד נתונים (מ-Java ל-SQL). כזכור, אנו הולכים להשתמש ביישום של מפרט JPA בשם Hibernate עבור זה:

dependencies {
	implementation 'com.h2database:h2:1.4.199'
	implementation 'org.hibernate:hibernate-core:5.4.2.Final'
כעת עלינו להגדיר את JPA. אם נקרא את המפרט והסעיף "8.1 יחידת התמדה", נדע שיחידת התמדה היא סוג של שילוב של תצורות, מטא נתונים וישויות. וכדי ש-JPA יפעל, אתה צריך לתאר לפחות יחידת התמדה אחת בקובץ התצורה, שנקרא persistence.xml. מיקומו מתואר בפרק המפרט "8.2 אריזת יחידת התמדה". לפי סעיף זה, אם יש לנו סביבת Java SE, אז עלינו לשים אותה בשורש של ספריית META-INF.
JPA: מבוא לטכנולוגיה - 6
הבה נעתיק את התוכן מהדוגמה המובאת במפרט JPA בפרק " 8.2.1 persistence.xml file":
<persistence>
	<persistence-unit name="JavaRush">
        <description>Persistence Unit For test</description>
        <class>hibernate.model.Category</class>
        <class>hibernate.model.Topic</class>
    </persistence-unit>
</persistence>
אבל זה לא מספיק. אנחנו צריכים להגיד מי הספק JPA שלנו, כלומר. מי שמיישם את מפרט JPA:
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
כעת נוסיף הגדרות ( properties). חלק מהן (החל ב javax.persistence) הן תצורות JPA סטנדרטיות ומתוארות במפרט JPA בסעיף "מאפיינים 8.2.1.9". חלק מהתצורות הן ספציפיות לספק (במקרה שלנו, הן משפיעות על Hibernate כספק Jpa. בלוק ההגדרות שלנו ייראה כך:
<properties>
    <property name="javax.persistence.jdbc.driver" value="org.h2.Driver" />
    <property name="javax.persistence.jdbc.url" value="jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE" />
    <property name="javax.persistence.jdbc.user" value="sa" />
    <property name="javax.persistence.jdbc.password" value="" />
    <property name="hibernate.show_sql" value="true" />
    <property name="hibernate.hbm2ddl.auto" value="create" />
</properties>
עכשיו יש לנו תצורה תואמת JPA persistence.xml, יש ספק JPA Hibernate ויש מסד נתונים H2, ויש גם 2 מחלקות שהן מודל התחום שלנו. סוף סוף נגרום לכל זה לעבוד. בקטלוג /test/java, Gradle שלנו יצר בחביבות תבנית למבחני יחידה וקרא לה AppTest. בואו נשתמש בו. כפי שנאמר בפרק "הקשרי התמדה 7.1" במפרט ה-JPA, ישויות בעולם ה-JPA חיות במרחב הנקרא ההקשר המתמשך. אבל אנחנו לא עובדים ישירות עם Context Context. לשם כך אנו משתמשים Entity Managerאו "מנהל ישות". הוא זה שיודע על ההקשר ואיזה ישויות חיות שם. אנחנו מקיימים אינטראקציה עם Entity Managerאום. אז כל מה שנותר הוא להבין מאיפה אנחנו יכולים להשיג את זה Entity Manager? לפי הפרק "7.2.2 השגת מנהל ישות מנוהל יישומים" של מפרט JPA, עלינו להשתמש ב- EntityManagerFactory. לכן, בואו נתחמש את עצמנו במפרט JPA וניקח דוגמה מהפרק "7.3.2 השגת מפעל של מנהל ישות בסביבת Java SE" ונעצב אותו בצורה של מבחן יחידה פשוט:
@Test
public void shouldStartHibernate() {
	EntityManagerFactory emf = Persistence.createEntityManagerFactory( "JavaRush" );
	EntityManager entityManager = emf.createEntityManager();
}
בדיקה זו כבר תציג את השגיאה "Uncognized JPA persistence.xml version XSD". הסיבה היא שעליך persistence.xmlלציין נכון את הסכימה לשימוש, כפי שמצוין במפרט JPA בסעיף "8.3 persistence.xml Schema":
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
             http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd"
             version="2.2">
בנוסף, יש חשיבות לסדר האלמנטים. לכן, providerיש לציין זאת לפני רישום השיעורים. לאחר מכן, הבדיקה תפעל בהצלחה. השלמנו את החיבור הישיר של JPA. לפני שנמשיך, בואו נחשוב על הבדיקות שנותרו. כל אחת מהבדיקות שלנו תדרוש EntityManager. בואו נוודא שלכל בדיקה יש משלה EntityManagerבתחילת הביצוע. בנוסף, אנו רוצים שבסיס הנתונים יהיה חדש בכל פעם. בשל העובדה שאנו משתמשים inmemoryבאפשרות, מספיק לסגור EntityManagerFactory. יצירה Factoryהיא פעולה יקרה. אבל לבדיקות זה מוצדק. JUnit מאפשר לך לציין שיטות שיבוצעו לפני (לפני) ואחרי (אחרי) ביצוע כל בדיקה:
public class AppTest {
    private EntityManager em;

    @Before
    public void init() {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory( "JavaRush" );
        em = emf.createEntityManager();
    }

    @After
    public void close() {
        em.getEntityManagerFactory().close();
        em.close();
    }
כעת, לפני ביצוע בדיקה כלשהי, ייווצר בדיקה חדשה EntityManagerFactoryשתגרום ליצירת מסד נתונים חדש, מכיוון hibernate.hbm2ddl.autoיש את המשמעות create. ומהמפעל החדש נקבל אחד חדש EntityManager.
JPA: מבוא לטכנולוגיה - 7

ישויות

כזכור, יצרנו בעבר מחלקות שמתארות את מודל התחום שלנו. כבר אמרנו שאלו הן ה"מהויות" שלנו. זו הישות שבה ננהל באמצעות EntityManager. בואו נכתוב מבחן פשוט כדי לשמור את המהות של קטגוריה:
@Test
public void shouldPersistCategory() {
	Category cat = new Category();
	cat.setTitle("new category");
	// JUnit обеспечит тест свежим EntityManager'ом
	em.persist(cat);
}
אבל הבדיקה הזו לא תעבוד מיד, כי... נקבל שגיאות שונות שיעזרו לנו להבין מהן ישויות:
  • Unknown entity: hibernate.model.Category
    למה Hibernate לא מבין מה Categoryזה entity? העניין הוא שיש לתאר ישויות לפי תקן JPA.
    יש לציין כיתות ישות עם ההערה @Entity, כמפורט בפרק "2.1 מחלקת הישות" של מפרט JPA.

  • No identifier specified for entity: hibernate.model.Category
    ישויות חייבות להיות בעל מזהה ייחודי שניתן להשתמש בו כדי להבחין בין רשומה אחת לאחרת.
    לפי הפרק "2.4 מפתחות ראשיים וזהות ישות" של מפרט JPA, "לכל ישות חייב להיות מפתח ראשי", כלומר. לכל ישות חייבת להיות "מפתח ראשי". מפתח ראשי כזה חייב להיות מוגדר על ידי ההערה@Id

  • ids for this class must be manually assigned before calling save()
    תעודת הזהות צריכה להגיע מאיפשהו. ניתן לציין זאת באופן ידני, או שניתן להשיגו באופן אוטומטי.
    לכן, כפי שצוין בפרקים "11.2.3.3 GeneratedValue" ו-"11.1.20 GeneratedValue Annotation", אנו יכולים לציין את ההערה @GeneratedValue.

אז כדי שמחלקת הקטגוריה תהפוך לישות עלינו לבצע את השינויים הבאים:
@Entity
public class Category {
    @Id
    @GeneratedValue
    private Long id;
בנוסף, ההערה @Idמציינת באיזה מהם להשתמש Access Type. תוכל לקרוא עוד על סוג הגישה במפרט JPA, בסעיף "2.3 סוג גישה". בקיצור, כי... ציינו @Idמעל השדה ( field), ואז סוג הגישה יהיה ברירת המחדל field-based, לא property-based. לכן, ספק JPA יקרא ויאחסן ערכים ישירות מהשדות. אם נמקם @Idמעל הגטר, אזי property-basedתשתמש בגישה, כלומר. דרך getter ו-seter. בעת הפעלת הבדיקה, אנו רואים גם אילו בקשות נשלחות למסד הנתונים (בזכות האפשרות hibernate.show_sql). אבל כששומרים, אנחנו לא רואים כלים insert. מסתבר שבעצם לא חסכנו כלום? JPA מאפשר לך לסנכרן את הקשר ההתמדה ואת מסד הנתונים באמצעות השיטה flush:
entityManager.flush();
אבל אם נבצע אותה כעת, נקבל שגיאה: שום עסקה לא מתבצעת . ועכשיו הגיע הזמן ללמוד כיצד JPA משתמש בעסקאות.
JPA: מבוא לטכנולוגיה - 8

עסקאות JPA

כזכור, JPA מבוסס על הרעיון של הקשר התמדה. זה המקום שבו חיות ישויות. ואנחנו מנהלים ישויות דרך EntityManager. כאשר אנו מבצעים את הפקודה persist, אנו ממקמים את הישות בהקשר. ליתר דיוק, אנחנו אומרים EntityManagerלך שזה צריך להיעשות. אבל ההקשר הזה הוא רק אזור אחסון כלשהו. זה אפילו נקרא לפעמים "מטמון ברמה הראשונה". אבל זה צריך להיות מחובר למסד הנתונים. הפקודה flush, שנכשלה בעבר עם שגיאה, מסנכרנת נתונים מהקשר ההתמדה עם מסד הנתונים. אבל זה מצריך הובלה והובלה זו עסקה. עסקאות ב-JPA מתוארות בסעיף "7.5 שליטה בעסקאות" של המפרט. יש API מיוחד לשימוש בעסקאות ב-JPA:
entityManager.getTransaction().begin();
entityManager.getTransaction().commit();
עלינו להוסיף ניהול עסקאות לקוד שלנו, שפועל לפני ואחרי בדיקות:
@Before
public void init() {
	EntityManagerFactory emf = Persistence.createEntityManagerFactory( "JavaRush" );
	em = emf.createEntityManager();
	em.getTransaction().begin();
}
@After
public void close() {
	if (em.getTransaction().isActive()) {
		em.getTransaction().commit();
        }
	em.getEntityManagerFactory().close();
	em.close();
}
לאחר הוספה, נראה ביומן ה-insert ביטוי ב-SQL שלא היה שם קודם:
JPA: מבוא לטכנולוגיה - 9
השינויים שנצברו בעסקה EntityManagerבוצעו (אושרו ונשמרו) במסד הנתונים. בואו ננסה כעת למצוא את המהות שלנו. בואו ניצור בדיקה לחיפוש ישות לפי המזהה שלה:
@Test
public void shouldFindCategory() {
	Category cat = new Category();
	cat.setTitle("test");
	em.persist(cat);
	Category result = em.find(Category.class, 1L);
	assertNotNull(result);
}
במקרה זה, נקבל את הישות ששמרנו בעבר, אך לא נראה את שאילתות ה-SELECT ביומן. והכל מבוסס על מה שאנחנו אומרים: "מנהל ישות, בבקשה מצא לי את ישות הקטגוריה עם ID=1." ומנהל הישות מחפש קודם כל בהקשר שלו (משתמש בסוג של מטמון), ורק אם הוא לא מוצא אותו, הוא הולך לחפש במסד הנתונים. כדאי לשנות את המזהה ל-2 (אין דבר כזה, שמרנו רק מופע אחד), ונראה שהבקשה SELECTמופיעה. מכיוון שלא נמצאו ישויות בהקשר ומסד EntityManagerהנתונים מנסה למצוא ישות ישנן פקודות שונות שבהן נוכל לשלוט במצב של ישות בהקשר. המעבר של ישות ממצב אחד לאחר נקרא מחזור החיים של הישות - lifecycle.
JPA: מבוא לטכנולוגיה - 10

מחזור חיים של ישות

מחזור החיים של ישויות מתואר במפרט JPA בפרק "3.2 מחזור החיים של מופע ישות". כי ישויות חיות בהקשר ונשלטות על ידי EntityManager, ואז אומרים שישויות נשלטות, כלומר. מנוהל. בואו נסתכל על שלבי החיים של ישות:
// 1. New or Transient (временный)
Category cat = new Category();
cat.setTitle("new category");
// 2. Managed or Persistent
entityManager.persist(cat);
// 3. Транзакция завершена, все сущности в контексте detached
entityManager.getTransaction().begin();
entityManager.getTransaction().commit();
// 4. Сущность изымаем из контекста, она становится detached
entityManager.detach(cat);
// 5. Сущность из detached можно снова сделать managed
Category managed = entityManager.merge(cat);
// 6. И можно сделать Removed. Интересно, что cat всё равно detached
entityManager.remove(managed);
והנה תרשים לאיחודו:
JPA: מבוא לטכנולוגיה - 11
JPA: מבוא לטכנולוגיה - 12

מיפוי

ב-JPA נוכל לתאר את היחסים של ישויות ביניהן. בואו נזכור שכבר הסתכלנו על מערכות היחסים של ישויות ביניהן כאשר עסקנו במודל התחום שלנו. לאחר מכן השתמשנו במשאב quickdatabasediagrams.com :
JPA: מבוא לטכנולוגיה - 13
יצירת קשרים בין ישויות נקראת מיפוי או אסוציאציה (Association Mappings). סוגי העמותות שניתן להקים באמצעות JPA מוצגים להלן:
JPA: מבוא לטכנולוגיה - 14
בואו נסתכל על ישות Topicשמתארת ​​נושא. מה אנחנו יכולים לומר על היחס Topicכלפי Category? רבים Topicיהיו שייכים לקטגוריה אחת. לכן, אנחנו צריכים עמותה ManyToOne. בואו נביע את הקשר הזה ב-JPA:
@ManyToOne
@JoinColumn(name = "category_id")
private Category category;
כדי לזכור אילו הערות לשים, ניתן לזכור שהחלק האחרון אחראי על השדה שמעליו מצוינת ההערה. ToOne- מופע ספציפי. ToMany- אוספים. עכשיו החיבור שלנו הוא חד כיווני. בואו נהפוך את זה לתקשורת דו כיוונית. בואו נוסיף Categoryלידע על כל מי Topicשנכלל בקטגוריה זו. זה חייב להסתיים ב ToMany, כי יש לנו רשימה Topic. כלומר, היחס "לרבים" נושאים. נותרה השאלה - OneToManyאו ManyToMany:
JPA: מבוא לטכנולוגיה - 15
תשובה טובה על אותו נושא ניתן לקרוא כאן: " הסבר ORM oneToMany, manyToMany קשר כמו I'm five ". אם לקטגוריה יש קשר עם ToManyנושאים, אז לכל אחד מהנושאים האלה יכול להיות רק קטגוריה אחת, אז זה יהיה One, אחרת Many. אז Categoryרשימת כל הנושאים תיראה כך:
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "topic_id")
private Set<Topic> topics = new HashSet<>();
ובואו לא נשכח בעצם Categoryלכתוב מגביר כדי לקבל רשימה של כל הנושאים:
public Set<Topic> getTopics() {
	return this.topics;
}
יחסים דו-כיווניים הם דבר שקשה מאוד לעקוב אחריהם באופן אוטומטי. לכן, JPA מעביר אחריות זו אל היזם. המשמעות עבורנו היא שכאשר אנו מקימים Topicמערכת יחסים של ישות עם Category, עלינו להבטיח עקביות נתונים בעצמנו. זה נעשה בפשטות:
public void setCategory(Category category) {
	category.getTopics().add(this);
	this.category = category;
}
בואו נכתוב מבחן פשוט לבדיקה:
@Test
public void shouldPersistCategoryAndTopics() {
	Category cat = new Category();
	cat.setTitle("test");
	Topic topic = new Topic();
	topic.setTitle("topic");
	topic.setCategory(cat);
 	em.persist(cat);
}
מיפוי הוא נושא נפרד לגמרי. מטרת סקירה זו היא להבין את האמצעים שבאמצעותם זה מושג. תוכל לקרוא עוד על מיפוי כאן:
JPA : מבוא לטכנולוגיה - 16

JPQL

JPA מציגה כלי מעניין - שאילתות בשפת השאילתות של Java Persistence. שפה זו דומה ל-SQL, אך משתמשת במודל האובייקט של Java ולא בטבלאות SQL. בואו נסתכל על דוגמה:
@Test
public void shouldPerformQuery() {
	Category cat = new Category();
	cat.setTitle("query");
	em.persist(cat);
	Query query = em.createQuery("SELECT c from Category c WHERE c.title = 'query'");
 	assertNotNull(query.getSingleResult());
}
כפי שאנו יכולים לראות, בשאילתה השתמשנו בהתייחסות לישות Categoryולא לטבלה. וגם במגרש של ישות זו title. JPQL מספק תכונות שימושיות רבות וראוי למאמר משלו. פרטים נוספים ניתן למצוא בסקירה:
JPA: מבוא לטכנולוגיה - 17

API של קריטריונים

ולבסוף, אני רוצה לגעת ב-Criteria API. JPA מציגה כלי לבניית שאילתות דינמית. דוגמה לשימוש ב-Criteria API:
@Test
public void shouldFindWithCriteriaAPI() {
	Category cat = new Category();
	em.persist(cat);
	CriteriaBuilder cb = em.getCriteriaBuilder();
	CriteriaQuery<Category> query = cb.createQuery(Category.class);
	Root<Category> c = query.from(Category.class);
	query.select(c);
	List<Category> resultList = em.createQuery(query).getResultList();
	assertEquals(1, resultList.size());
}
דוגמה זו מקבילה לביצוע הבקשה " SELECT c FROM Category c". ה-Criteria API הוא כלי רב עוצמה. אתה יכול לקרוא עוד על זה כאן:

סיכום

כפי שאנו יכולים לראות, JPA מספק מספר עצום של תכונות וכלים. כל אחד מהם דורש ניסיון וידע. גם במסגרת סקירת ה-JPA לא ניתן היה להזכיר הכל, שלא לדבר על צלילה מפורטת. אבל אני מקווה שאחרי שקראתי אותו, התברר יותר מה זה ORM ו-JPA, איך זה עובד ומה אפשר לעשות איתם. ובכן, עבור חטיף אני מציע חומרים שונים: #ויאצ'סלב
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION