Tetapkan data dengan Objek Data Java, Bahagian 1

"Semuanya harus dibuat sesederhana mungkin, tetapi tidak lebih sederhana."

Albert Einstein

Keperluan untuk mengekalkan data yang dibuat pada masa berjalan sama seperti komputer. Dan keperluan untuk menyimpan data berorientasi objek muncul ketika pengaturcaraan berorientasi objek menjadi meluas. Pada masa ini, aplikasi yang paling moden dan tidak biasa menggunakan paradigma berorientasi objek untuk memodelkan domain aplikasi. Sebaliknya, pasaran pangkalan data lebih terbahagi. Sebilangan besar sistem pangkalan data menggunakan model hubungan, tetapi penyimpanan data berdasarkan objek terbukti sangat diperlukan dalam banyak aplikasi. Selain itu, kami juga mempunyai sistem warisan yang sering kami perlukan untuk dihubungkan.

Artikel ini mengidentifikasi masalah yang berkaitan dengan ketekunan data dalam lingkungan perisian tengah transaksional, seperti J2EE (Java 2 Platform, Enterprise Edition), dan menunjukkan bagaimana Java Data Objects (JDO) menyelesaikan beberapa masalah tersebut. Artikel ini memberikan gambaran keseluruhan, bukan tutorial terperinci, dan ditulis dari sudut pandangan pembangun aplikasi, bukan perancang pelaksanaan JDO.

Baca keseluruhan siri pada Objek Data Java:

  • Bahagian 1. Pahami kualiti di sebalik lapisan kegigihan yang ideal
  • Bahagian 2. Sun JDO vs Castor JDO

Para pemaju Java, pereka, dan arkitek J2EE yang bekerja pada sistem yang mesti menyimpan data dalam pangkalan data relasional atau objek, atau media penyimpanan lain harus membaca artikel ini. Saya menganggap anda mempunyai pengetahuan asas mengenai Java dan beberapa keakraban dengan masalah dan terminologi hubungan objek.

Ketekunan telus: Mengapa bersusah payah?

Lebih dari satu dekad percubaan berterusan untuk merapatkan jangka masa dan ketekunan berorientasikan objek menunjukkan beberapa pemerhatian penting (disenaraikan mengikut urutan kepentingan):

  1. Mengasingkan setiap butiran kegigihan dan memiliki API yang bersih, sederhana, berorientasikan objek untuk melakukan penyimpanan data adalah yang terpenting. Kami tidak mahu menangani perincian ketekunan dan perwakilan data dalaman di kedai data, sama ada hubungannya, berdasarkan objek, atau yang lain. Mengapa kita harus berurusan dengan konstruksi tahap rendah model penyimpanan data, seperti baris dan lajur, dan terus menerus menerjemahkannya berulang-ulang? Sebaliknya, kita perlu menumpukan perhatian pada aplikasi rumit yang harus kita sampaikan semalam.
  2. Kami ingin menggunakan pendekatan plug-and-play dengan penyimpanan data kami: Kami ingin menggunakan penyedia / implementasi yang berbeza tanpa mengubah sebaris kod sumber aplikasi - dan mungkin tanpa mengubah lebih dari beberapa baris dalam fail konfigurasi yang sesuai ( s). Dengan kata lain, kita memerlukan standard industri untuk mengakses data berdasarkan objek Java, yang memainkan peranan serupa dengan yang dimainkan JDBC (Java Database Connectivity) sebagai standard industri untuk mengakses data berdasarkan SQL.
  3. Kami ingin menggunakan pendekatan plug-and-play dengan paradigma pangkalan data yang berbeza - iaitu, kami ingin beralih dari pangkalan data relasional ke yang berorientasi objek dengan perubahan minimum pada kod aplikasi. Walaupun senang dimiliki, dalam praktiknya, kemampuan ini sering tidak diperlukan.

    Satu komen di sini: Walaupun pangkalan data relasional menikmati kehadiran pasar terbesar sejauh ini, menyediakan API ketekunan bersatu dan membolehkan penyedia penyimpanan data bersaing dengan kekuatan pelaksanaan masuk akal, tanpa mengira paradigma yang digunakan penyedia ini. Pendekatan ini akhirnya dapat membantu meratakan persaingan antara dua kumpulan vendor pangkalan data yang dominan: kem relasional yang mapan dan kem berorientasikan objek yang berjuang untuk pasaran.

Ketiga penemuan yang disenaraikan di atas membawa kita untuk menentukan lapisan ketekunan, kerangka yang menyediakan API Java tingkat tinggi untuk objek dan hubungan untuk hidup lebih lama dari jangka hayat persekitaran runtime (JVM). Kerangka seperti itu mesti mempunyai kualiti berikut:

  • Kesederhanaan
  • Pencerobohan minimum
  • Ketelusan, yang bermaksud kerangka kerja menyembunyikan pelaksanaan penyimpanan data
  • API yang konsisten dan ringkas untuk penyimpanan / pengambilan / kemas kini objek
  • Sokongan transaksi, yang bermaksud rangka menentukan semantik transaksional yang berkaitan dengan objek berterusan
  • Sokongan untuk kedua-dua persekitaran yang dikendalikan (contohnya, berasaskan pelayan aplikasi) dan juga persekitaran yang tidak dikendalikan (mandiri)
  • Sokongan untuk tambahan yang diperlukan, seperti cache, pertanyaan, penjanaan kunci utama, dan alat pemetaan
  • Bayaran pelesenan yang berpatutan - bukan keperluan teknikal, tetapi kita semua tahu bahawa ekonomi yang buruk dapat menjatuhkan projek yang sangat baik

Saya memperincikan kebanyakan kualiti di atas di bahagian berikut.

Kesederhanaan

Tahap kesederhanaan tinggi dalam senarai ciri yang diperlukan untuk kerangka perisian atau perpustakaan apa pun (lihat petikan pembukaan artikel ini). Membangunkan aplikasi yang diedarkan sudah cukup sukar, dan banyak projek perisian gagal kerana pengurusan yang kompleks (dan, secara meluas, risiko) yang buruk. Simple tidak sinonim dengan simplistic; perisian harus mempunyai semua ciri yang diperlukan yang membolehkan pembangun melakukan tugasnya.

Pencerobohan minimum

Setiap sistem simpanan berterusan memperkenalkan sejumlah pencerobohan ke dalam kod aplikasi. Lapisan ketekunan yang ideal harus meminimumkan pencerobohan untuk mencapai modulariti yang lebih baik dan, dengan itu, fungsi plug-and-play.

Untuk tujuan artikel ini, saya mendefinisikan pencerobohan sebagai:

  • Jumlah kod khusus ketekunan tersebar di seluruh kod aplikasi
  • Keperluan untuk memodifikasi model objek aplikasi anda dengan harus menggunakan beberapa antarmuka ketekunan - seperti Persistableatau sejenisnya - atau dengan memproses kod yang dihasilkan

Pencerobohan juga berlaku untuk sistem pangkalan data berorientasi objek dan, walaupun biasanya masalahnya lebih sedikit dibandingkan dengan penyimpanan data hubungan, ia boleh berbeza secara signifikan di antara vendor ODBMS (sistem pengurusan pangkalan data berorientasikan objek).

Ketelusan

Konsep ketelusan lapisan berterusan cukup sederhana: aplikasi menggunakan API yang sama tanpa mengira jenis penyimpanan data (ketelusan jenis penyimpanan data), atau vendor penyimpanan data (ketelusan penyimpanan data-vendor). Ketelusan sangat memudahkan aplikasi dan meningkatkan kebolehlangsungannya dengan menyembunyikan perincian pelaksanaan penyimpanan data ke tahap semaksimum mungkin. Khususnya, untuk penyimpanan data hubungan yang lazim, tidak seperti JDBC, anda tidak perlu membuat penyataan SQL atau nama lajur yang keras, atau mengingat urutan lajur yang dikembalikan oleh pertanyaan. Sebenarnya, anda tidak perlu mengetahui SQL atau aljabar relasional, kerana ia terlalu spesifik pelaksanaannya. Ketelusan mungkin merupakan sifat terpenting lapisan kegigihan.

API yang konsisten dan ringkas

API lapisan kegigihan turun ke set operasi yang agak kecil:

  • Operasi CRUD Elementary (buat, baca, kemas kini, hapus) pada objek kelas pertama
  • Pengurusan urus niaga
  • Pengurusan aplikasi dan identiti objek-kegigihan
  • Pengurusan cache (iaitu, menyegarkan dan mengusir)
  • Pembuatan dan pelaksanaan pertanyaan

Contoh PersistenceLayerAPI:

kekosongan awam berterusan (Objek obj); // Simpan obj ke stor data. beban Objek awam (Kelas c, Objek pK); // Baca obj dengan kunci utama yang diberikan. kemas kini kekosongan awam (Objek obj); // Kemas kini objek yang diubah. kekosongan awam kosong (Objek obj); // Padamkan obj dari pangkalan data. temuan Koleksi awam (Pertanyaan q); // Cari objek yang memenuhi syarat permintaan kami.

Sokongan transaksi

Lapisan ketekunan yang baik memerlukan beberapa fungsi asas untuk memulakan, melakukan, atau memutar balik transaksi. Berikut adalah contoh:

// Transaction (tx) demarcation. public void startTx(); public void commitTx(); public void rollbackTx(); // Choose to make a persistent object transient after all. public void makeTransient(Object o) 

Note: Transaction demarcation APIs are primarily used in nonmanaged environments. In managed environments, the built-in transaction manager often assumes this functionality.

Managed environments support

Managed environments, such as J2EE application servers, have grown popular with developers. Who wants to write middle tiers from scratch these days when we have excellent application servers available? A decent persistence layer should be able to work within any major application server's EJB (Enterprise JavaBean) container and synchronize with its services, such as JNDI (Java Naming and Directory Interface) and transaction management.

Queries

The API should be able to issue arbitrary queries for data searches. It should include a flexible and powerful, but easy-to-use, language -- the API should use Java objects, not SQL tables or other data-store representations as formal query parameters.

Cache management

Cache management can do wonders for application performance. A sound persistence layer should provide full data caching as well as appropriate APIs to set the desired behavior, such as locking levels, eviction policies, lazy loading, and distributed caching support.

Primary key generation

Providing automatic identity generation for data is one of the most common persistence services. Every decent persistence layer should provide identity generation, with support for all major primary key-generation algorithms. Primary key generation is a well-researched issue and numerous primary key algorithms exist.

Mapping, for relational databases only

With relational databases, a data mapping issue arises: the need to translate objects into tables, and to translate relationships, such as dependencies and references, into additional columns or tables. This is a nontrivial problem in itself, especially with complex object models. The topic of object-relational model impedance mismatch reaches beyond this article's scope, but is well publicized. See Resources for more information.

The following list of extras related to mapping and/or relational data stores are not required in the persistence layer, but they make a developer's life much easier:

  • A GUI (graphical user interface) mapping tool
  • Code generators: Autogeneration of DDL (data description language) to create database tables, or autogeneration of Java code and mapping files from DDL
  • Primary key generators: Supporting multiple key-generation algorithms, such as UUID, HIGH-LOW, and SEQUENCE
  • Support for binary large objects (BLOBs) and character-based large objects (CLOBs)
  • Self-referential relations: An object of type Bar referencing another object of type Bar, for example
  • Raw SQL support: Pass-through SQL queries

Example

The following code snippet shows how to use the persistence layer API. Suppose we have the following domain model: A company has one or more locations, and each location has one or more users. The following could be an example application's code:

PersistenceManager pm =PMFactory.initialize(..); Company co = new Company("MyCompany"); Location l1 = new Location1 ("Boston"); Location l2 = new Location("New York"); // Create users. User u1 = new User("Mark"); User u2 = new User("Tom"); User u3 = new User("Mary"); // Add users. A user can only "belong" to one location. L1.addUser(u1); L1.addUser(u2); L2.addUser(u3); // Add locations to the company. co.addLocation(l1); co.addLocation(l2); // And finally, store the whole tree to the database. pm.persist(c); 

In another session, you can look up companies employing the user Tom:

PersistenceManager pm =PMFactory.initialize(...) Collection companiesEmployingToms = pm.find("company.location.user.name = 'Tom'"); 

Untuk penyimpanan data hubungan, anda mesti membuat fail pemetaan tambahan. Mungkin kelihatan seperti ini:

    Pengguna Lokasi Syarikat             

Lapisan ketekunan menguruskan selebihnya, yang merangkumi yang berikut:

  • Mencari kumpulan objek bergantung
  • Menguruskan identiti objek aplikasi
  • Menguruskan identiti objek berterusan (kunci utama)
  • Mengekalkan setiap objek mengikut urutan yang sesuai
  • Menyediakan pengurusan cache
  • Menyediakan konteks transaksional yang betul (kami tidak mahu hanya sebahagian pokok objek bertahan, bukan?)
  • Menyediakan mod penguncian yang boleh dipilih pengguna