JPA คืออะไร? บทนำสู่ Java Persistence API
ตามข้อกำหนด Java Persistence API เกี่ยวข้องกับการคงอยู่ซึ่งหมายถึงกลไกแบบหลวม ๆ ที่วัตถุ Java อยู่ได้นานกว่ากระบวนการแอปพลิเคชันที่สร้างขึ้น ไม่ใช่ทุกอ็อบเจ็กต์ Java ที่ต้องคงอยู่ แต่แอ็พพลิเคชันส่วนใหญ่ยังคงมีอ็อบเจ็กต์ทางธุรกิจที่สำคัญ ข้อกำหนด JPA ช่วยให้คุณกำหนดซึ่งวัตถุที่ควรได้รับการยืนยันและวิธีการที่วัตถุเหล่านั้นควรได้รับการยืนยันในการใช้งานจาวาของคุณ
ด้วยตัวมันเอง JPA ไม่ใช่เครื่องมือหรือกรอบ แต่เป็นการกำหนดชุดของแนวคิดที่สามารถนำไปใช้โดยเครื่องมือหรือกรอบงานใดก็ได้ ในขณะที่แบบจำลองการทำแผนที่เชิงสัมพันธ์เชิงวัตถุ (ORM) ของ JPA เดิมมีพื้นฐานมาจาก Hibernate แต่ก็มีการพัฒนาตั้งแต่นั้นมา ในทำนองเดียวกันในขณะที่ JPA เดิมมีไว้สำหรับใช้กับฐานข้อมูลเชิงสัมพันธ์ / SQL การใช้งาน JPA บางส่วนได้รับการขยายเพื่อใช้กับที่เก็บข้อมูล NoSQL เฟรมเวิร์กยอดนิยมที่รองรับ JPA กับ NoSQL คือ EclipseLink ซึ่งเป็นการนำไปใช้อ้างอิงสำหรับ JPA 2.2
JPA 2.2 ในจาการ์ตา EE
Java Persistence API เปิดตัวครั้งแรกเป็นชุดย่อยของข้อกำหนด EJB 3.0 (JSR 220) ใน Java EE 5 ตั้งแต่นั้นมาได้มีการพัฒนาเป็นข้อมูลจำเพาะของตัวเองโดยเริ่มจากการเปิดตัว JPA 2.0 ใน Java EE 6 (JSR 317) ในขณะที่เขียนนี้ JPA 2.2 ได้ถูกนำมาใช้เพื่อดำเนินการต่อโดยเป็นส่วนหนึ่งของ Jakarta EE
JPA และ Hibernate
เนื่องจากประวัติศาสตร์ที่เกี่ยวพันกัน Hibernate และ JPA จึงถูกรวมเข้าด้วยกันบ่อยครั้ง อย่างไรก็ตามเช่นเดียวกับข้อกำหนด Java Servlet JPA ได้สร้างเครื่องมือและเฟรมเวิร์กที่เข้ากันได้มากมาย ไฮเบอร์เนตเป็นเพียงหนึ่งในนั้น
พัฒนาโดย Gavin King และเปิดตัวในต้นปี 2545 Hibernate เป็นไลบรารี ORM สำหรับ Java King พัฒนา Hibernate เพื่อเป็นทางเลือกให้กับถั่วเอนทิตีเพื่อการคงอยู่ เฟรมเวิร์กได้รับความนิยมอย่างมากและจำเป็นมากในเวลานั้นแนวคิดหลายอย่างถูกนำมาใช้และประมวลผลในข้อกำหนด JPA แรก
ปัจจุบัน Hibernate ORM เป็นหนึ่งในการใช้งาน JPA ที่เป็นผู้ใหญ่ที่สุดและยังคงเป็นตัวเลือกยอดนิยมสำหรับ ORM ใน Java ไฮเบอร์เนต ORM 5.3.8 (เวอร์ชันปัจจุบัน ณ การเขียนนี้) ใช้ JPA 2.2 นอกจากนี้กลุ่มเครื่องมือของ Hibernate ได้ขยายไปถึงเครื่องมือยอดนิยมเช่น Hibernate Search, Hibernate Validator และ Hibernate OGM ซึ่งรองรับการคงอยู่ของโมเดลโดเมนสำหรับ NoSQL
JPA และ EJB
ดังที่ระบุไว้ก่อนหน้า JPA ถูกนำมาใช้เป็นชุดย่อยของ EJB 3.0 แต่ได้มีการพัฒนาเป็นข้อกำหนดของตัวเอง EJB เป็นข้อกำหนดที่มีจุดเน้นแตกต่างจาก JPA และถูกนำไปใช้ในคอนเทนเนอร์ EJB คอนเทนเนอร์ EJB แต่ละตัวมีเลเยอร์การคงอยู่ซึ่งกำหนดโดยข้อกำหนดของ JPA
Java ORM คืออะไร?
แม้ว่าจะแตกต่างกันในการดำเนินการ แต่การใช้งาน JPA ทุกครั้งจะมีเลเยอร์ ORM บางประเภท เพื่อให้เข้าใจถึงเครื่องมือที่เข้ากันได้กับ JPA และ JPA คุณต้องมีความเข้าใจที่ดีเกี่ยวกับ ORM
การทำแผนที่เชิงสัมพันธ์กับวัตถุเป็นงานที่นักพัฒนามีเหตุผลที่ดีที่จะหลีกเลี่ยงการทำด้วยตนเอง กรอบเช่น Hibernate ออมหรือ EclipseLink codifies งานที่เข้ามาในห้องสมุดหรือกรอบการชั้นออม ในฐานะส่วนหนึ่งของสถาปัตยกรรมแอ็พพลิเคชันเลเยอร์ ORM มีหน้าที่จัดการการแปลงอ็อบเจ็กต์ซอฟต์แวร์เพื่อโต้ตอบกับตารางและคอลัมน์ในฐานข้อมูลเชิงสัมพันธ์ ใน Java เลเยอร์ ORM จะแปลงคลาส Java และอ็อบเจ็กต์เพื่อให้สามารถจัดเก็บและจัดการในฐานข้อมูลเชิงสัมพันธ์ได้
ตามค่าเริ่มต้นชื่อของวัตถุที่ยังคงอยู่จะกลายเป็นชื่อของตารางและเขตข้อมูลจะกลายเป็นคอลัมน์ เมื่อตั้งค่าตารางแล้วแต่ละแถวของตารางจะสอดคล้องกับวัตถุในแอปพลิเคชัน การแมปวัตถุสามารถกำหนดค่าได้ แต่ค่าเริ่มต้นมักจะทำงานได้ดี
JPA กับ NoSQL
จนกระทั่งเมื่อไม่นานมานี้ฐานข้อมูลที่ไม่ใช่เชิงสัมพันธ์เป็นสิ่งที่ไม่ธรรมดา การเคลื่อนไหวของ NoSQL เปลี่ยนไปทั้งหมดและตอนนี้นักพัฒนา Java มีฐานข้อมูล NoSQL ที่หลากหลาย การใช้งาน JPA บางอย่างได้รับการพัฒนาเพื่อรองรับ NoSQL รวมถึง Hibernate OGM และ EclipseLink
รูปที่ 1 แสดงให้เห็นถึงบทบาทของ JPA และเลเยอร์ ORM ในการพัฒนาแอปพลิเคชัน

การกำหนดค่าเลเยอร์ Java ORM
เมื่อคุณตั้งค่าโปรเจ็กต์ใหม่เพื่อใช้ JPA คุณจะต้องกำหนดค่าผู้ให้บริการข้อมูลและ JPA คุณจะกำหนดค่าตัวเชื่อมต่อที่เก็บข้อมูลเพื่อเชื่อมต่อกับฐานข้อมูลที่คุณเลือก (SQL หรือ NoSQL) คุณจะรวมและกำหนดค่าผู้ให้บริการ JPAซึ่งเป็นเฟรมเวิร์กเช่น Hibernate หรือ EclipseLink แม้ว่าคุณจะสามารถกำหนดค่า JPA ได้ด้วยตนเอง แต่นักพัฒนาหลายคนก็เลือกใช้การสนับสนุนแบบสำเร็จรูปของ Spring โปรดดู " การติดตั้งและการตั้งค่า JPA " ด้านล่างสำหรับการสาธิตการติดตั้งและการตั้งค่า JPA ทั้งแบบแมนนวลและแบบสปริง
Java Data Objects
Java Data Objects เป็นเฟรมเวิร์กการคงอยู่ที่เป็นมาตรฐานซึ่งแตกต่างจาก JPA เป็นหลักโดยการสนับสนุนตรรกะการคงอยู่ในออบเจ็กต์และด้วยการสนับสนุนที่ยาวนานสำหรับการทำงานกับที่เก็บข้อมูลที่ไม่ใช่เชิงสัมพันธ์ JPA และ JDO มีความคล้ายคลึงกันเพียงพอที่ผู้ให้บริการ JDO มักสนับสนุน JPA ดู Apache JDO Project เพื่อเรียนรู้เพิ่มเติมเกี่ยวกับ JDO ที่เกี่ยวข้องกับมาตรฐานการคงอยู่อื่น ๆ เช่น JPA และ JDBC
การคงอยู่ของข้อมูลใน Java
จากมุมมองของการเขียนโปรแกรมเลเยอร์ ORM เป็นเลเยอร์อะแด็ปเตอร์ : ปรับภาษาของกราฟออบเจ็กต์เป็นภาษาของ SQL และตารางเชิงสัมพันธ์ เลเยอร์ ORM ช่วยให้นักพัฒนาเชิงวัตถุสามารถสร้างซอฟต์แวร์ที่เก็บข้อมูลไว้ได้โดยไม่ต้องออกจากกระบวนทัศน์เชิงวัตถุ
เมื่อคุณใช้ JPA คุณจะสร้างแผนที่จากที่เก็บข้อมูลไปยังวัตถุโมเดลข้อมูลของแอปพลิเคชันของคุณ แทนที่จะกำหนดวิธีการบันทึกและเรียกใช้อ็อบเจ็กต์คุณกำหนดการแม็ประหว่างอ็อบเจ็กต์และฐานข้อมูลของคุณจากนั้นเรียกใช้ JPA เพื่อคงอยู่ หากคุณใช้ฐานข้อมูลเชิงสัมพันธ์การเชื่อมต่อจริงส่วนใหญ่ระหว่างรหัสแอปพลิเคชันของคุณและฐานข้อมูลจะถูกจัดการโดย JDBC, Java Database Connectivity API
ตามข้อมูลจำเพาะ JPA จัดเตรียมคำอธิบายประกอบข้อมูลเมตาซึ่งคุณใช้กำหนดการแมประหว่างอ็อบเจ็กต์และฐานข้อมูล การใช้งาน JPA แต่ละครั้งจะมีเครื่องมือของตัวเองสำหรับคำอธิบายประกอบ JPA ข้อมูลจำเพาะ JPA ยังให้PersistanceManager
หรือEntityManager
ซึ่งเป็นจุดสำคัญในการติดต่อกับระบบ JPA (โดยรหัสตรรกะทางธุรกิจของคุณจะบอกระบบว่าจะทำอย่างไรกับวัตถุที่แมป)
เพื่อให้ทั้งหมดนี้เป็นรูปธรรมมากขึ้นให้พิจารณา Listing 1 ซึ่งเป็นคลาสข้อมูลง่ายๆสำหรับการสร้างโมเดลนักดนตรี
รายการ 1. คลาสข้อมูลอย่างง่ายใน Java
public class Musician { private Long id; private String name; private Instrument mainInstrument; private ArrayList performances = new ArrayList(); public Musician( Long id, String name){ /* constructor setters... */ } public void setName(String name){ this.name = name; } public String getName(){ return this.name; } public void setMainInstrument(Instrument instr){ this.instrument = instr; } public Instrument getMainInstrument(){ return this.instrument; } // ...Other getters and setters... }
Musician
เรียนในรายการที่ 1 จะใช้ในการรักษาข้อมูล สามารถมีข้อมูลดั้งเดิมเช่นฟิลด์ชื่อ นอกจากนี้ยังสามารถเก็บความสัมพันธ์จากการเรียนอื่น ๆ เช่นและmainInstrument
performances
Musician
's เหตุผลสำหรับความเป็นอยู่คือการประกอบด้วยข้อมูล ประเภทของชั้นนี้บางครั้งก็เป็นที่รู้จักกัน DTO หรือวัตถุการถ่ายโอนข้อมูล DTO เป็นคุณสมบัติทั่วไปของการพัฒนาซอฟต์แวร์ แม้ว่าจะมีข้อมูลหลายประเภท แต่ก็ไม่มีตรรกะทางธุรกิจใด ๆ วัตถุข้อมูลที่คงอยู่เป็นความท้าทายที่แพร่หลายในการพัฒนาซอฟต์แวร์
การคงอยู่ของข้อมูลด้วย JDBC
วิธีหนึ่งในการบันทึกอินสแตนซ์ของMusician
คลาสลงในฐานข้อมูลเชิงสัมพันธ์คือการใช้ไลบรารี JDBC JDBC เป็นชั้นของนามธรรมที่ช่วยให้แอปพลิเคชันออกคำสั่ง SQL โดยไม่ต้องคิดถึงการใช้ฐานข้อมูลพื้นฐาน
รายการ 2 แสดงให้เห็นว่าคุณสามารถคงMusician
คลาสโดยใช้ JDBC ได้อย่างไร
รายการ 2. JDBC การแทรกเร็กคอร์ด
Musician georgeHarrison = new Musician(0, "George Harrison"); String myDriver = "org.gjt.mm.mysql.Driver"; String myUrl = "jdbc:mysql://localhost/test"; Class.forName(myDriver); Connection conn = DriverManager.getConnection(myUrl, "root", ""); String query = " insert into users (id, name) values (?, ?)"; PreparedStatement preparedStmt = conn.prepareStatement(query); preparedStmt.setInt (1, 0); preparedStmt.setString (2, "George Harrison"); preparedStmt.setString (2, "Rubble"); preparedStmt.execute(); conn.close(); // Error handling removed for brevity
รหัสในรายการที่ 2 เป็นเอกสารในตัวเองอย่างเป็นธรรม georgeHarrison
วัตถุอาจจะมาจากที่ใดก็ได้ (Front-end ส่งบริการภายนอกอื่น ๆ ) และมี ID และเขตข้อมูลชื่อชุด จากนั้นฟิลด์บนอ็อบเจ็กต์จะถูกใช้เพื่อจัดหาค่าของinsert
คำสั่งSQL ( PreparedStatement
คลาสเป็นส่วนหนึ่งของ JDBC ซึ่งนำเสนอวิธีการนำค่าไปใช้กับแบบสอบถาม SQL อย่างปลอดภัย)
แม้ว่า JDBC จะอนุญาตให้มีการควบคุมที่มาพร้อมกับการกำหนดค่าด้วยตนเอง แต่ก็ยุ่งยากเมื่อเทียบกับ JPA ในการแก้ไขฐานข้อมูลก่อนอื่นคุณต้องสร้างแบบสอบถาม SQL ที่แมปจากวัตถุ Java ของคุณไปยังตารางในฐานข้อมูลเชิงสัมพันธ์ จากนั้นคุณต้องแก้ไข SQL เมื่อใดก็ตามที่ลายเซ็นของวัตถุเปลี่ยนแปลง ด้วย JDBC การดูแล SQL จะกลายเป็นงานในตัวเอง
การคงอยู่ของข้อมูลด้วย JPA
ตอนนี้ให้พิจารณา Listing 3 ซึ่งเราคงอยู่ในMusician
ชั้นเรียนโดยใช้ JPA
Listing 3. Persisting George Harrison with JPA
Musician georgeHarrison = new Musician(0, "George Harrison"); musicianManager.save(georgeHarrison);
Listing 3 replaces the manual SQL from Listing 2 with a single line, session.save()
, which instructs JPA to persist the object. From then on, the SQL conversion is handled by the framework, so you never have to leave the object-oriented paradigm.
Metadata annotations in JPA
The magic in Listing 3 is the result of a configuration, which is created using JPA's annotations. Developers use annotations to inform JPA which objects should be persisted, and how they should be persisted.
Listing 4 shows the Musician
class with a single JPA annotation.
Listing 4. JPA's @Entity annotation
@Entity public class Musician { // ..class body }
Persistent objects are sometimes called entities. Attaching @Entity
to a class like Musician
informs JPA that this class and its objects should be persisted.
XML vs. annotation-based configuration
JPA also supports using external XML files, instead of annotations, to define class metadata. But why would you do that to yourself?
Configuring JPA
Like most modern frameworks, JPA embraces coding by convention (also known as convention over configuration), in which the framework provides a default configuration based on industry best practices. As one example, a class named Musician
would be mapped by default to a database table called Musician.
The conventional configuration is a timesaver, and in many cases it works well enough. It is also possible to customize your JPA configuration. As an example, you could use JPA's @Table
annotation to specify the table where the Musician
class should be stored.
Listing 5. JPA's @Table annotation
@Entity @Table(name="musician") public class Musician { // ..class body }
Listing 5 tells JPA to persist the entity (Musician
class) to the musician
table.
Primary key
In JPA, the primary key is the field used to uniquely identify each object in the database. The primary key is useful for referencing and relating objects to other entities. Whenever you store an object in a table, you will also specify the field to use as its primary key.
In Listing 6, we tell JPA what field to use as Musician
's primary key.
Listing 6. Specifying the primary key
@Entity public class Musician { @Id private Long id;
In this case, we've used JPA's @Id
annotation to specify the id
field as Musician
's primary key. By default, this configuration assumes the primary key will be set by the database--for instance, when the field is set to auto-increment on the table.
JPA supports other strategies for generating an object's primary key. It also has annotations for changing individual field names. In general, JPA is flexible enough to adapt to any persistence mapping you might need.
CRUD operations
Once you've mapped a class to a database table and established its primary key, you have everything you need to create, retrieve, delete, and update that class in the database. Calling session.save()
will create or update the specified class, depending on whether the primary-key field is null or applies to en existing entity. Calling entityManager.remove()
will delete the specified class.
Entity relationships in JPA
Simply persisting an object with a primitive field is only half the equation. JPA also has the capability to manage entities in relation to one another. Four kinds of entity relationships are possible in both tables and objects:
- One-to-many
- Many-to-one
- Many-to-many
- One-to-one
Each type of relationship describes how an entity relates to other entities. For example, the Musician
entity could have a one-to-many relationship with Performance
, an entity represented by a collection such as List
or Set
.
If the Musician
included a Band
field, the relationship between these entities could be many-to-one, implying collection of Musician
s on the single Band
class. (Assuming each musician only performs in a single band.)
If Musician
included a BandMates
field, that could represent a many-to-many relationship with other Musician
entities.
สุดท้ายMusician
อาจจะมีความสัมพันธ์แบบหนึ่งต่อหนึ่งกับนิติบุคคลที่ใช้ในการเป็นตัวแทนของการพูดที่มีชื่อเสียง:Quote
Quote famousQuote = new Quote()
การกำหนดประเภทความสัมพันธ์
JPA มีคำอธิบายประกอบสำหรับประเภทการแมปความสัมพันธ์แต่ละประเภท รายการ 7 แสดงให้เห็นว่าคุณสามารถใส่คำอธิบายประกอบความสัมพันธ์แบบหนึ่งต่อกลุ่มระหว่างMusician
และPerformance
s ได้อย่างไร