Apa itu Hibernasi? Dasar implementasi Hibernate Core
Diterbitkan: 2013-04-17Hibernate adalah proyek kerangka kerja persistensi Java open source. Lakukan pemetaan relasional objek dan database kueri yang kuat menggunakan HQL dan SQL.
Secara umum perpustakaan yang banyak digunakan dirancang dan diimplementasikan dengan baik, dan sangat menarik untuk belajar dari mereka beberapa praktik terbaik pengkodean.
Mari kita lihat di dalam pustaka inti hibernasi dan temukan beberapa kunci desainnya.
Dalam posting ini Hibernate Core dianalisis oleh JArchitect
untuk masuk jauh ke dalam desain dan implementasinya.
Paket berdasarkan Fitur
Package-by-feature
menggunakan paket untuk mencerminkan kumpulan fitur. Ini menempatkan semua item yang terkait dengan satu fitur (dan hanya fitur itu) ke dalam satu direktori/paket. Ini menghasilkan paket dengan kohesi tinggi dan modularitas tinggi, dan dengan kopling minimal antar paket. Item yang bekerja sama ditempatkan di samping satu sama lain.
Inti hibernate berisi banyak paket, masing-masing terkait dengan fitur tertentu hql, sql, dan lain-lain.
Kopel
Kopling rendah diinginkan karena perubahan di satu area aplikasi akan membutuhkan lebih sedikit perubahan di seluruh aplikasi. Dalam jangka panjang, ini dapat mengurangi banyak waktu, tenaga, dan biaya yang terkait dengan modifikasi dan penambahan fitur baru ke aplikasi.
Berikut adalah tiga manfaat utama yang diperoleh dari penggunaan antarmuka:
- Antarmuka menyediakan cara untuk menentukan kontrak yang mempromosikan penggunaan kembali. Jika suatu objek mengimplementasikan antarmuka maka objek itu harus sesuai dengan standar. Sebuah objek yang menggunakan objek lain disebut konsumen. Antarmuka adalah kontrak antara objek dan konsumennya.
- Antarmuka juga menyediakan tingkat abstraksi yang membuat program lebih mudah dipahami. Antarmuka memungkinkan pengembang untuk mulai berbicara tentang cara umum kode berperilaku tanpa harus masuk ke banyak detail spesifik.
- Sebuah antarmuka menegakkan kopling rendah antara komponen, apa yang membuat mudah untuk melindungi konsumen antarmuka dari setiap perubahan implementasi di kelas yang mengimplementasikan antarmuka.
Mari kita cari semua interface yang didefinisikan oleh Hibernate Core, untuk itu kita menggunakan CQLinq
untuk query basis kode.
1 |
from t in Types where t . IsInterface select t |
Jika tujuan utama kami adalah untuk menegakkan kopling rendah, ada kesalahan umum saat menggunakan antarmuka yang dapat mematikan utilitas menggunakannya. Ini adalah penggunaan kelas konkret alih-alih antarmuka, dan untuk menjelaskan masalah ini dengan lebih baik, mari kita ambil contoh berikut:
Kelas A mengimplementasikan Antarmuka IA yang berisi metode hitung(), kelas konsumen C diimplementasikan seperti itu
1 2 3 4 5 6 7 8 9 10 11 |
public class C < br > { … . public void calculate ( ) { … . . m_a . calculate ( ) ; … . } A m_a ; } |
Kelas C bukannya mereferensikan antarmuka IA, melainkan merujuk ke kelas A, dalam hal ini kita kehilangan manfaat kopling rendah, dan implementasi ini memiliki dua kelemahan utama:
- Jika kita memutuskan untuk menggunakan implementasi IA lain, kita harus mengubah kode kelas C.
- Jika beberapa metode ditambahkan ke A yang tidak ada di IA, dan C menggunakannya, kami juga kehilangan manfaat kontrak dari penggunaan antarmuka.
C# memperkenalkan kemampuan implementasi antarmuka eksplisit ke bahasa untuk memastikan bahwa metode dari IA tidak akan pernah dipanggil dari referensi ke kelas konkret, tetapi hanya dari referensi ke antarmuka. Teknik ini sangat berguna untuk melindungi pengembang dari kehilangan manfaat menggunakan antarmuka.
Dengan JArchitect kita dapat memeriksa kesalahan semacam ini menggunakan CQLinq
, idenya adalah untuk mencari semua metode dari kelas beton yang digunakan langsung oleh metode lain.
1 2 3 4 5 6 7 8 9 |
from m in Methods where m . NbMethodsCallingMe > 0 && m . ParentType . IsClass && ! m . ParentType . IsThirdParty && ! m . ParentType . IsAbstract let interfaces = m . ParentType . InterfacesImplemented from i in interfaces where i . Methods . Where ( a = > a . Name == m . Name && a . ParentType ! = m . ParentType ) . Count ( ) > 0 select new { m , m . ParentType , i } |
Misalnya metode getEntityPersister dari SessionFactoryImpl yang mengimplementasikan antarmuka SessionFactoryImplementor terkait dengan masalah ini.
Mari kita cari metode yang memanggil langsung SessionFactoryImpl.getEntityPersister.
1 2 3 |
from m in Methods where m . IsUsing ( "org.hibernate.internal.SessionFactoryImpl.getEntityPersister(String)" ) select new { m , m . NbBCInstructions } |

Metode seperti SessionImpl.instantiate memanggil langsung getEntityPersister, alih-alih melewati antarmuka, yang merusak manfaat menggunakan antarmuka. Untungnya inti hibernasi tidak mengandung banyak metode yang memiliki masalah ini.
Kopling dengan stoples eksternal
Ketika lib eksternal digunakan, lebih baik untuk memeriksa apakah kita dapat dengan mudah mengubah lib pihak ketiga dengan yang lain tanpa memengaruhi seluruh aplikasi, ada banyak alasan yang dapat mendorong kita untuk mengubah lib pihak ketiga.
Lib lainnya dapat:
- Memiliki lebih banyak fitur
- Lebih bertenaga
- Lebih aman
Mari kita ambil contoh antlr lib
yang digunakan untuk mengurai query hql, dan bayangkan parser lain yang lebih kuat dari antlr telah dibuat, dapatkah kita mengubah antlr dengan parser baru dengan mudah?
Untuk menjawab pertanyaan ini mari kita cari metode mana dari hibernate yang menggunakannya secara langsung:
1 2 3 |
from m in Methods where m . IsUsing ( "antlr-2.7.7" ) select new { m , m . NbBCInstructions } |
Dan mana yang menggunakannya secara tidak langsung:
1 2 3 4 |
from m in Projects . WithNameNotIn ( "antlr-2.7.7" ) . ChildMethods ( ) let depth0 = m . DepthOfIsUsing ( "antlr-2.7.7" ) where depth0 > 1 orderby depth0 select new { m , depth0 } |
Banyak metode menggunakan antlr secara langsung yang membuat inti hibernasi sangat digabungkan dengannya, dan mengubah antlr dengan yang lain bukanlah tugas yang mudah. fakta ini tidak berarti bahwa kami memiliki masalah dalam desain hibernasi, tetapi kami harus berhati-hati saat menggunakan lib pihak ketiga dan memeriksa apakah lib pihak ketiga harus rendah digabungkan atau tidak dengan aplikasi.
Kohesi
Prinsip tanggung jawab tunggal menyatakan bahwa kelas harus memiliki satu, dan hanya satu, alasan untuk berubah. Kelas seperti itu dikatakan kohesif. Nilai LCOM
yang tinggi umumnya menunjukkan kelas kohesif yang buruk. Ada beberapa metrik LCOM. LCOM mengambil nilainya dalam kisaran [0-1]. LCOMHS (HS singkatan dari Henderson-Sellers) mengambil nilainya dalam kisaran [0-2]. Perhatikan bahwa metrik LCOMHS sering dianggap lebih efisien untuk mendeteksi jenis non-kohesif.
Nilai LCOMHS yang lebih tinggi dari 1 harus dianggap mengkhawatirkan.
Secara umum kelas yang lebih mementingkan kohesi adalah kelas yang memiliki banyak metode dan bidang.
Mari kita cari tipe yang memiliki banyak metode dan bidang.
1 2 3 4 |
from t in Types where ( t . Methods . Count ( ) > 40 | | t . Fields . Count ( ) > 40 ) && t . IsClass orderby t . Methods . Count ( ) descending select new { t , t . InstanceMethods , t . Fields , t . LCOMHS } |
Hanya beberapa jenis yang diperhatikan oleh kueri ini, dan untuk semuanya LCOMHS kurang dari 1.
Menggunakan Anotasi
Pengembangan berbasis anotasi membebaskan pengembang Java dari kerumitan konfigurasi yang rumit. Dan beri kami fitur canggih untuk membebaskan kode sumber dari kode boilerplate. Kode yang dihasilkan juga cenderung tidak mengandung bug.
Mari kita cari semua anotasi yang ditentukan oleh inti hibernasi.
1 |
from t in Types where t . IsAnnotationClass && ! t . IsThirdParty select t |
Banyak anotasi yang ditentukan, yang membuat hibernasi mudah digunakan oleh pengembang, dan kerumitan file konfigurasi dapat dihindari.
Kesimpulan
Hibernate Core adalah contoh bagus dari proyek open source untuk dipelajari, jangan ragu untuk melihat ke dalamnya.