Pemintas Hibernate

1. Gambaran keseluruhan

Dalam perbincangan ini, kita akan melihat pelbagai cara memintas operasi dalam pelaksanaan pemetaan hubungan abstrak Hibernate.

2. Mendefinisikan Interceptors Hibernate

Hibernate Interceptor adalah antara muka yang membolehkan kita bertindak balas terhadap peristiwa tertentu dalam Hibernate.

Pemintas ini didaftarkan sebagai panggilan balik dan menyediakan hubungan komunikasi antara sesi dan aplikasi Hibernate. Dengan panggilan balik seperti itu, aplikasi dapat memintas operasi inti Hibernate seperti menyimpan, mengemas kini, menghapus, dll.

Terdapat dua cara untuk menentukan pemintas:

  1. melaksanakan antara muka org.hibernate.Interceptor
  2. memanjangkan kelas org.hibernate.EmptyInterceptor

2.1. Melaksanakan Antaramuka Interceptor

Melaksanakan org.hibernate.Interceptor memerlukan pelaksanaan kira-kira 14 kaedah yang disertakan . Kaedah ini merangkumi onLoad, onSave, onDelete, findDirty, dan beberapa lagi.

Ini juga penting untuk memastikan bahawa mana-mana kelas yang melaksanakan antara muka Interceptor boleh diselaraskan ( menerapkan java.io.Serializable )

Contoh biasa akan kelihatan seperti:

public class CustomInterceptorImpl implements Interceptor, Serializable { @Override public boolean onLoad(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) throws CallbackException { // ... return false; } // ... @Override public String onPrepareStatement(String sql) { // ... return sql; } }

Sekiranya tidak ada syarat khas, perluasan kelas EmptyInterceptor dan hanya mengatasi kaedah yang diperlukan sangat digalakkan.

2.2. Memperluas EmptyInterceptor

Memperluas kelas org.hibernate.EmptyInterceptor menyediakan kaedah yang lebih mudah untuk menentukan pemintas. Kita sekarang hanya perlu mengesampingkan kaedah yang berkaitan dengan operasi yang kita mahu memintas.

Sebagai contoh, kami dapat menentukan CustomInterceptor kami sebagai:

public class CustomInterceptor extends EmptyInterceptor { }

Dan jika kita perlu memintas operasi penjimatan data sebelum dijalankan, kita perlu mengganti kaedah onSave :

@Override public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) { if (entity instanceof User) { logger.info(((User) entity).toString()); } return super.onSave(entity, id, state, propertyNames, types); }

Perhatikan bagaimana pelaksanaan ini hanya mencetak entiti - jika itu Pengguna .

Walaupun ia mungkin untuk kembali nilai benar atau palsu , ia adalah satu amalan yang baik untuk membolehkan penyebaran onSave acara dengan memohon super.onSave () .

Kes penggunaan lain ialah menyediakan jejak audit untuk interaksi pangkalan data. Kita boleh menggunakan kaedah onFlushDirty () untuk mengetahui bila entiti berubah.

Untuk objek Pengguna , kami dapat memutuskan untuk mengemas kini harta tarikh terakhirnya yang diubah setiap kali berlaku perubahan pada entiti jenis Pengguna .

Ini dapat dicapai dengan:

@Override public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, Object [] previousState, String[] propertyNames, Type[] types) { if (entity instanceof User) { ((User) entity).setLastModified(new Date()); logger.info(((User) entity).toString()); } return super.onFlushDirty(entity, id, currentState, previousState, propertyNames, types); }

Kejadian lain seperti hapus dan muat (inisialisasi objek) dapat dipintas dengan melaksanakan kaedah onDelete dan onLoad yang sesuai masing-masing.

3. Mendaftar Pemintas

Pemintas Hibernate boleh didaftarkan sebagai Session -scoped atau SessionFactory-scoped .

3.1. Pemintas yang merangkumi sesi

A Sesi pemintas -scoped dikaitkan dengan sesi tertentu. Ia dibuat semasa sesi ditakrifkan atau dibuka sebagai:

public static Session getSessionWithInterceptor(Interceptor interceptor) throws IOException { return getSessionFactory().withOptions() .interceptor(interceptor).openSession(); }

Di atas, kami secara jelas mendaftarkan pemintas dengan sesi hibernasi tertentu.

3.2. Interceptor berskala kilang

A SessionFactory- skop pemintas didaftarkan sebelum membina SessionFactory. Ini biasanya dilakukan melalui kaedah applyInterceptor pada contoh SessionFactoryBuilder :

ServiceRegistry serviceRegistry = configureServiceRegistry(); SessionFactory sessionFactory = getSessionFactoryBuilder(serviceRegistry) .applyInterceptor(new CustomInterceptor()) .build();

Penting untuk diperhatikan bahawa pemintas yang diliputi SessionFactory akan digunakan untuk semua sesi. Oleh itu, kita perlu berhati-hati untuk tidak menyimpan keadaan khusus sesi - kerana pemintas ini akan digunakan oleh sesi yang berbeza secara serentak.

Untuk tingkah laku khusus sesi, disarankan untuk membuka sesi secara jelas dengan pemintas yang berbeza seperti yang ditunjukkan sebelumnya.

Untuk pemintas yang dilengkapkan dengan SessionFactory, kita semestinya perlu memastikannya selamat. Ini dapat dicapai dengan menentukan konteks sesi dalam fail sifat:

hibernate.current_session_context_class=org.hibernate.context.internal.ThreadLocalSessionContext

Atau dengan menambahkannya ke fail konfigurasi XML kami:

 org.hibernate.context.internal.ThreadLocalSessionContext 

Juga, untuk memastikan kebolehpasaran , pemintas yang dilancarkan SessionFactory mesti melaksanakan kaedah readResolve pada antara muka Serializable .

4. Kesimpulan

Kami telah melihat bagaimana menentukan dan mendaftarkan pemintas Hibernate sama ada sebagai Session- scoped atau SessionFactory -scoped. Dalam kedua-dua kes tersebut, kita mesti memastikan bahawa pemintas dapat disenaraikan terutamanya jika kita mahu sesi bersiri.

Alternatif lain untuk pemintas termasuk Hibernate Events dan JPA Callbacks.

Dan, seperti biasa, anda boleh melihat kod sumber lengkap di Github.