Apa itu JPA? Pengantar Java Persistence API

Sebagai spesifikasi, Java Persistence API berkaitan dengan persistensi , yang secara longgar berarti mekanisme apa pun yang membuat objek Java hidup lebih lama dari proses aplikasi yang membuatnya. Tidak semua objek Java perlu dipertahankan, tetapi sebagian besar aplikasi mempertahankan objek bisnis utama. Spesifikasi JPA memungkinkan Anda menentukan objek mana yang harus dipertahankan, dan bagaimana objek tersebut harus dipertahankan dalam aplikasi Java Anda.

Dengan sendirinya, JPA bukanlah alat atau kerangka kerja; sebaliknya, ini mendefinisikan sekumpulan konsep yang dapat diimplementasikan oleh alat atau kerangka kerja apa pun. Sementara model object-relational mapping (ORM) JPA awalnya didasarkan pada Hibernate, model ini telah berkembang. Demikian juga, sementara JPA pada awalnya ditujukan untuk digunakan dengan database relasional / SQL, beberapa implementasi JPA telah diperluas untuk digunakan dengan database NoSQL. Kerangka kerja populer yang mendukung JPA dengan NoSQL adalah EclipseLink, implementasi referensi untuk JPA 2.2.

JPA 2.2 di Jakarta EE

Java Persistence API pertama kali dirilis sebagai bagian dari spesifikasi EJB 3.0 (JSR 220) di Java EE 5. Sejak saat itu API tersebut berkembang sebagai spesifikasinya sendiri, dimulai dengan rilis JPA 2.0 di Java EE 6 (JSR 317). Sampai tulisan ini dibuat, JPA 2.2 telah diadopsi untuk kelanjutan sebagai bagian dari Jakarta EE.

JPA dan Hibernate

Karena sejarahnya yang saling terkait, Hibernate dan JPA sering kali digabungkan. Namun, seperti spesifikasi Java Servlet, JPA telah melahirkan banyak alat dan kerangka kerja yang kompatibel; Hibernasi hanyalah salah satunya.

Dikembangkan oleh Gavin King dan dirilis pada awal 2002, Hibernate adalah pustaka ORM untuk Java. King mengembangkan Hibernate sebagai alternatif kacang entitas untuk ketekunan. Kerangka kerja tersebut sangat populer, dan sangat dibutuhkan pada saat itu, sehingga banyak dari idenya diadopsi dan dikodifikasi dalam spesifikasi JPA yang pertama.

Saat ini, Hibernate ORM adalah salah satu implementasi JPA yang paling matang, dan masih menjadi pilihan populer untuk ORM di Java. Hibernate ORM 5.3.8 (versi saat ini saat tulisan ini dibuat) mengimplementasikan JPA 2.2. Selain itu, rangkaian alat Hibernate telah diperluas untuk menyertakan alat populer seperti Hibernate Search, Hibernate Validator, dan Hibernate OGM, yang mendukung persistensi model domain untuk NoSQL.

JPA dan EJB

Seperti disebutkan sebelumnya, JPA diperkenalkan sebagai bagian dari EJB 3.0, tetapi sejak itu berkembang sebagai spesifikasinya sendiri. EJB adalah spesifikasi dengan fokus yang berbeda dari JPA, dan diimplementasikan dalam wadah EJB. Setiap penampung EJB menyertakan lapisan persistensi, yang ditentukan oleh spesifikasi JPA.

Apa itu Java ORM?

Meskipun berbeda dalam pelaksanaannya, setiap implementasi JPA menyediakan beberapa jenis lapisan ORM. Untuk memahami alat yang kompatibel dengan JPA dan JPA, Anda harus memiliki pemahaman yang baik tentang ORM.

Pemetaan objek-relasional adalah tugas –suatu yang pengembang memiliki alasan kuat untuk tidak melakukannya secara manual. Kerangka kerja seperti Hibernate ORM atau EclipseLink mengkodifikasikan tugas itu ke dalam pustaka atau kerangka kerja, lapisan ORM . Sebagai bagian dari arsitektur aplikasi, lapisan ORM bertanggung jawab untuk mengelola konversi objek perangkat lunak untuk berinteraksi dengan tabel dan kolom dalam database relasional. Di Java, lapisan ORM mengonversi kelas dan objek Java sehingga dapat disimpan dan dikelola dalam database relasional.

Secara default, nama objek yang dipertahankan menjadi nama tabel, dan bidang menjadi kolom. Setelah tabel disiapkan, setiap baris tabel sesuai dengan objek dalam aplikasi. Pemetaan objek dapat dikonfigurasi, tetapi default cenderung bekerja dengan baik.

JPA dengan NoSQL

Sampai baru-baru ini, database non-relasional adalah keingintahuan yang tidak umum. Gerakan NoSQL mengubah semua itu, dan sekarang berbagai database NoSQL tersedia untuk pengembang Java. Beberapa implementasi JPA telah berkembang untuk merangkul NoSQL, termasuk Hibernate OGM dan EclipseLink.

Gambar 1 mengilustrasikan peran JPA dan lapisan ORM dalam pengembangan aplikasi.

JavaWorld /

Mengonfigurasi lapisan ORM Java

Saat menyiapkan project baru untuk menggunakan JPA, Anda perlu mengonfigurasi penyedia datastore dan JPA. Anda akan mengonfigurasi konektor datastore untuk terhubung ke database yang Anda pilih (SQL atau NoSQL). Anda juga akan menyertakan dan mengkonfigurasi penyedia JPA , yang merupakan kerangka kerja seperti Hibernate atau EclipseLink. Meskipun Anda dapat mengonfigurasi JPA secara manual, banyak pengembang memilih untuk menggunakan dukungan luar biasa Spring. Lihat " Penginstalan dan pengaturan JPA " di bawah ini untuk demonstrasi penginstalan dan pengaturan JPA manual dan berbasis Spring.

Objek Data Java

Objek Data Java adalah kerangka kerja ketekunan standar yang berbeda dari JPA terutama dengan mendukung logika ketekunan dalam objek, dan dengan dukungan lama untuk bekerja dengan penyimpanan data non-relasional. JPA dan JDO cukup mirip sehingga penyedia JDO seringkali juga mendukung JPA. Lihat Proyek Apache JDO untuk mempelajari lebih lanjut tentang JDO sehubungan dengan standar persistensi lain seperti JPA dan JDBC.

Persistensi data di Java

Dari perspektif pemrograman, lapisan ORM adalah lapisan adaptor : ia menyesuaikan bahasa grafik objek dengan bahasa SQL dan tabel relasional. Lapisan ORM memungkinkan pengembang berorientasi objek untuk membangun perangkat lunak yang menyimpan data tanpa pernah meninggalkan paradigma berorientasi objek.

Saat Anda menggunakan JPA, Anda membuat peta dari datastore ke objek model data aplikasi Anda. Alih-alih menentukan bagaimana objek disimpan dan diambil, Anda menentukan pemetaan antara objek dan database Anda, lalu memanggil JPA untuk mempertahankannya. Jika Anda menggunakan database relasional, sebagian besar koneksi aktual antara kode aplikasi Anda dan database kemudian akan ditangani oleh JDBC, Java Database Connectivity API.

Sebagai spesifikasi, JPA menyediakan anotasi metadata , yang Anda gunakan untuk menentukan pemetaan antara objek dan database. Setiap implementasi JPA menyediakan mesinnya sendiri untuk anotasi JPA. Spesifikasi JPA juga menyediakan PersistanceManageratau EntityManager, yang merupakan titik kontak utama dengan sistem JPA (di mana kode logika bisnis Anda memberi tahu sistem apa yang harus dilakukan dengan objek yang dipetakan).

Untuk membuat semua ini lebih konkret, pertimbangkan Daftar 1, yang merupakan kelas data sederhana untuk pemodelan musisi.

Kode 1. Kelas data sederhana di Jawa

 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... } 

The Musiciankelas Listing 1 digunakan untuk data yang ditahan. Ini bisa berisi data primitif seperti kolom nama . Itu juga dapat mengadakan hubungan dengan kelas lain seperti mainInstrumentdan performances.

Musician's alasan makhluk adalah untuk berisi data. Jenis kelas ini terkadang dikenal sebagai DTO, atau objek transfer data . DTO adalah fitur umum dari pengembangan perangkat lunak. Meskipun mereka menyimpan banyak jenis data, mereka tidak mengandung logika bisnis apa pun. Objek data yang ada merupakan tantangan di mana-mana dalam pengembangan perangkat lunak.

Persistensi data dengan JDBC

Salah satu cara untuk menyimpan instance Musiciankelas ke database relasional adalah dengan menggunakan pustaka JDBC. JDBC adalah lapisan abstraksi yang memungkinkan aplikasi mengeluarkan perintah SQL tanpa memikirkan implementasi database yang mendasarinya.

Kode 2 menunjukkan bagaimana Anda bisa bertahan di Musiciankelas menggunakan JDBC.

Kode 2. JDBC memasukkan catatan

 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 

Kode pada Listing 2 cukup terdokumentasi sendiri. The georgeHarrisonobjek bisa datang dari mana saja (front-end mengirimkan, layanan eksternal, dll), dan telah bidang ID dan nama yang ditetapkan. Bidang pada objek kemudian digunakan untuk memberikan nilai insertpernyataan SQL . ( PreparedStatementKelas adalah bagian dari JDBC, menawarkan cara untuk menerapkan nilai dengan aman ke kueri SQL.)

Meskipun JDBC memungkinkan kontrol yang dilengkapi dengan konfigurasi manual, ini lebih rumit dibandingkan dengan JPA. Untuk memodifikasi database, Anda harus terlebih dahulu membuat kueri SQL yang memetakan dari objek Java Anda ke tabel dalam database relasional. Anda kemudian harus mengubah SQL setiap kali tanda tangan objek berubah. Dengan JDBC, memelihara SQL menjadi tugas tersendiri.

Persistensi data dengan JPA

Sekarang pertimbangkan Listing 3, di mana kami mempertahankan Musiciankelas menggunakan 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:

    1. One-to-many
    2. Many-to-one
    3. Many-to-many
    4. 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 Musicians 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.

Akhirnya, Musicianmungkin memiliki hubungan satu-ke-satu dengan Quoteentitas, yang digunakan untuk mewakili kutipan terkenal: Quote famousQuote = new Quote().

Mendefinisikan jenis hubungan

JPA memiliki penjelasan untuk setiap jenis pemetaan hubungannya. Kode 7 menunjukkan bagaimana Anda dapat menjelaskan hubungan satu-ke-banyak antara Musiciandan Performances.

Daftar 7. Anotasi hubungan satu-ke-banyak