Kapan dan mengapa entitas JPA harus mengimplementasikan antarmuka Serializable?

151

Pertanyaannya ada di judul. Di bawah ini saya baru saja menggambarkan beberapa pemikiran dan temuan saya.

Ketika saya memiliki model domain yang sangat sederhana (3 tabel tanpa hubungan apa pun) semua entitas saya TIDAK mengimplementasikan Serializable.

Tetapi ketika model domain menjadi lebih kompleks saya mendapat RuntimeException yang mengatakan bahwa salah satu entitas saya tidak mengimplementasikan Serializable.

Saya menggunakan Hibernate sebagai implementasi JPA.

Aku penasaran:

  1. Apakah itu persyaratan / perilaku khusus vendor?
  2. Apa yang terjadi dengan entitas serializable saya? Haruskah serial dapat disimpan atau disimpan?
  3. Pada saat mana menjadi perlu untuk membuat entitas saya serializable?
Roma
sumber

Jawaban:

59

Ini biasanya terjadi jika Anda mencampur permintaan HQL dan SQL asli. Di HQL, Hibernate memetakan tipe yang Anda berikan pada apa pun yang dimengerti DB. Ketika Anda menjalankan SQL asli, maka Anda harus melakukan pemetaan sendiri. Jika tidak, maka pemetaan default adalah membuat cerita bersambung parameter dan mengirimkannya ke database (dengan harapan ia memahaminya).

Aaron Digulla
sumber
Ini tidak menjelaskan mengapa "mungkin bagaimana" Lihat jawaban di bawah ini dari Bozho
chrips
Apakah entitas yang berarti akan disimpan dalam DB tanpa mengimplementasikan antarmuka serializable?
Hanumantha_3048092
@ Hanumantha_3048092 Ya. Pemetaan entitas dan Serializabledua konsep yang berbeda.
Aaron Digulla
@ AaronDigulla Bisakah Anda jelaskan dengan contoh atau kode semu.
sdindiver
110

Menurut JPA Spec:

Jika instance entitas harus diteruskan oleh nilai sebagai objek terpisah (misalnya, melalui antarmuka jarak jauh), kelas entitas harus mengimplementasikan antarmuka Serializable.

"JSR 220: Enterprise JavaBeansTM, Versi 3.0 Java Persistence API Versi 3.0, Rilis Final 2 Mei 2006"

Conor
sumber
14
(+1) melihat spek selalu berbuah
Bozho
20
Saya gagal melihat mengapa ini memiliki begitu banyak upvotes. OP mengatakan bahwa itu tidak diperlukan ketika modelnya lebih sederhana. Mengirim objek dari jarak jauh melalui serialisasi Java akan SELALU membutuhkan objek yang akan Serializable, terlepas dari kompleksitasnya. Jelas ini bukan kasus penggunaan OP.
Robin
Saya tidak begitu yakin tentang hibernate, tetapi dengan penyedia JPA lain ada operasi yang mengharuskan penyedia untuk membuat salinan suatu entitas (objek). Serializablebisa membantu dengan itu, dan dalam konteks kegigihan lebih konsisten daripada Cloneablemisalnya.
JimmyB 6-15
Jawaban ini hanyalah dump info dan sama sekali tidak membantu seseorang memahami mengapa.
chrips
59

Anda membutuhkan entitas Anda Serializable Anda jika Anda perlu mentransfernya secara over-the-wire (cerita bersambung ke beberapa representasi lain), menyimpannya dalam sesi http (yang kemudian serial ke hard disk oleh wadah servlet), dll.

Hanya demi kegigihan, Serializabletidak diperlukan, setidaknya dengan Hibernate. Tapi itu adalah praktik terbaik untuk membuatnya Serializable.

Bozho
sumber
2
Saya tidak tahu, mungkin entitas saya dipindahkan secara implisit di suatu tempat. Saya menggunakan hibernate + spring + jsf dan Tomcat. Di mana dalam rantai transfer ini dapat terjadi?
Roman
@Roman misalnya pengguna saat ini (yang mungkin merupakan entitas) dan semua entitas terkaitnya mungkin berakhir di sesi, yang seperti yang dikatakan Bozho dapat diserialisasi ke disk oleh wadah servlet.
OrangeDog
INI adalah jawaban terbaik "mengapa dan kapan"! Bersih! Terima kasih
chrips
13

Menurut dokumen hibernasi , saat menggunakan penjelasan @JoinColumn:

Ini memiliki satu parameter bernama referencedColumnName. Parameter ini menyatakan kolom dalam entitas yang ditargetkan yang akan digunakan untuk bergabung. Perhatikan bahwa ketika menggunakan referencedColumnNamekolom bukan kunci utama, kelas terkait harus Serializable.

aman maharjan
sumber
8

Untuk melengkapi jawaban bagus Conor yang merujuk pada spesifikasi JSR-317. Biasanya, proyek EAR terdiri dari modul EJB dengan EJB diekspos melalui antarmuka jarak jauh. Dalam hal ini, Anda perlu membuat kacang entitas Anda serializable karena diagregasi dalam EJB jarak jauh dan dibuat untuk dihubungkan melalui jaringan.

Proyek perang JEE6 tanpa CDI: dapat mengandung EJB lite yang didukung oleh entitas JPA yang tidak dapat diserialisasi.

Proyek perang JEE6 dengan CDI: Kacang yang menggunakan cakupan sesi, aplikasi, atau percakapan harus serial, tetapi kacang yang menggunakan ruang lingkup permintaan tidak harus serial. Jadi entitas JPA yang mendasari kacang - jika ada - akan mengikuti semantik yang sama.

Simbol-Simbol
sumber
7

Jika kita hanya berbicara tentang kegigihan, Serializabletidak diperlukan. Tetapi merupakan praktik terbaik untuk membuat entitas Serializable.

Jika kita mengekspos domain/ entitiesobjek yang langsung terpapar ke lapisan presentasi, alih-alih menggunakan DTO, Dalam hal ini kita perlu menerapkan Serializable. Objek domain ini dapat disimpan HTTPSessionuntuk tujuan caching / optimisasi. Sesi http dapat diserialisasi atau dikelompokkan. Dan itu juga diperlukan untuk mentransfer data antar- JVMkeadaan.

Ketika kita gunakan DTOuntuk memisahkan lapisan kegigihan dan lapisan layanan, menandai objek domain sebagai Serializablekontra produktif dan akan melanggar " encapsulation". Maka itu menjadi anti-pola.

Pengidentifikasi komposit

Kelas kunci utama harus serial.

Model POJO

Jika instance entitas akan digunakan dari jarak jauh sebagai objek terpisah, kelas entitas harus mengimplementasikan Serializableantarmuka.

Cache
Selain itu, jika Anda menerapkan clusteredlevel kedua cachemaka entitas Anda harus serializable. Pengidentifikasi harus Serializablekarena itu adalah persyaratan JPA karena identifiermungkin digunakan sebagai kunci untuk entri cache tingkat kedua.

Dan ketika kita membuat serial entitas memastikan untuk memberikan eksplisit serialVersionUIDdengan pengubah akses pribadi. Karena jika suatu serializablekelas tidak secara eksplisit mendeklarasikan a serialVersionUID, maka runtime serialisasi akan menghitung serialVersionUIDnilai default untuk kelas tersebut berdasarkan berbagai aspek kelas, seperti yang dijelaskan dalam Spesifikasi Serialisasi Objek Java (TM). serialVersionUIDKomputasi default sangat sensitif terhadap detail kelas yang dapat bervariasi tergantung pada implementasi kompiler, dan dengan demikian dapat mengakibatkan hal yang tidak terduga InvalidClassExceptionsselama deserialisasi.

Ankur Singhal
sumber
6

Saya percaya masalah Anda terkait dengan memiliki bidang tipe kompleks (kelas) yang tidak dijelaskan. Dalam kasus seperti itu penanganan default akan menyimpan objek dalam bentuk serial di database (yang mungkin bukan yang Anda maksudkan) Contoh:

Class CustomerData {
    int getAge();
    void setAge(int age);
}

@Entity
Class Customer {
  CustomerData getCustomerData();
  void setCustomerData(CustomerData data)
}

Dalam kasus di atas, CustomerData akan disimpan dalam bidang array byte dalam database dalam bentuk serial.

Avner Levy
sumber
5

Spesifikasi JPA

Menurut spesifikasi JPA, suatu entitas harus menerapkan Serializablehanya jika perlu diteruskan dari satu JVM ke yang lain atau jika entitas tersebut digunakan oleh Stateful Session Bean yang perlu dipasivasi oleh wadah EJB.

Jika instance entitas harus diteruskan oleh nilai sebagai objek terpisah (misalnya, melalui antarmuka jarak jauh), kelas entitas harus mengimplementasikan Serializableantarmuka.

Hibernasi

Hibernate hanya membutuhkan atribut entitas Serializable, tetapi bukan entitas itu sendiri.

Namun, dengan menerapkan spesifikasi JPA, semua persyaratan JPA mengenai Serializableentitas juga berlaku untuk Hibernate.

Kucing jantan

Menurut dokumentasi Tomcat , HttpSessionatributnya juga harus Serializable:

Setiap kali Apache Tomcat dimatikan secara normal dan dihidupkan ulang, atau ketika sebuah aplikasi dimuat kembali dipicu, implementasi standar Manager akan mencoba untuk membuat serial semua sesi yang sedang aktif ke file disk yang terletak melalui atribut pathname. Semua sesi yang disimpan tersebut kemudian akan di-deserialisasi dan diaktifkan (dengan asumsi mereka belum kedaluwarsa dalam waktu yang bersamaan) ketika memuat ulang aplikasi selesai.

Agar berhasil mengembalikan keadaan atribut sesi, semua atribut tersebut HARUS mengimplementasikan antarmuka java.io.Serializable.

Jadi, jika entitas disimpan dalam HttpSession, itu harus diimplementasikan Serializable.

Vlad Mihalcea
sumber
4

Kelas harus mengimplementasikan Serializable jika Anda ingin membuat cerita bersambung. Ini tidak terkait langsung dengan JPA dan spesifikasi JPA tidak mengharuskan entitas serializable. Jika Hibernate benar-benar mengeluh tentang ini, saya kira itu adalah bug Hibernate, tapi saya kira Anda secara langsung atau tidak langsung melakukan sesuatu yang lain dengan entitas, yang mengharuskan mereka untuk serial.

jarnbjo
sumber
3

Silakan merujuk http://www.adam-bien.com/roller/abien/entry/do_jpa_entities_have_to mengatakan, Implementasi java.io.Serializable hanya diperlukan untuk mentransfer data melalui IIOP atau JRMP (RMI) antara instance JVM. Dalam kasus aplikasi web murni objek domain kadang-kadang disimpan dalam HTTPSession untuk tujuan caching / optimasi. Sesi http dapat diserialisasi (pasif) atau dikelompokkan. Dalam kedua kasus semua konten harus Serializable.

Arun K
sumber
1

hit jarak jauh menggunakan tukang pos atau ajax atau angular js dll ....., dapat menyebabkan siklus berulang dengan pengecualian StackOverflow dengan Jackson fastxml. Jadi, lebih baik menggunakan serializer.

Tamil
sumber
1
  1. Pada saat mana menjadi perlu untuk membuat entitas saya serializable?

Menerapkan ehcache dengan diskstore sebagai cache level kedua (yaitu menggunakan @Cacheableanotasi entitas atau metode repositori / layanan) memerlukan Serializable, jika tidak cache akan gagal ( NotSerializableException) untuk menulis entitas ke cache disk.

Michal
sumber
0

Ini juga merupakan kesalahan yang dilemparkan ketika Anda memberikan ID yang salah ketik sebagai param kedua untuk sesuatu seperti em.find () (yaitu dengan meneruskan entitas itu sendiri daripada ID-nya). Saya belum merasa perlu untuk benar-benar mendeklarasikan entitas JPA serializable - itu tidak benar-benar diperlukan kecuali jika Anda menggunakan referencedColumnName seperti yang dijelaskan oleh aman.

Amalgovinus
sumber
0

ketika entitas JPA digunakan sebagai parameter atau mengembalikan nilai oleh operasi EJB jarak jauh

SAR
sumber