JPA varlıkları ne zaman ve neden Serileştirilebilir arabirimi uygulamalıdır?


156

Soru başlıkta. Aşağıda bazı düşüncelerimi ve bulgularımı açıkladım.

Çok basit bir etki alanı modelim olduğunda (herhangi bir ilişkisiz 3 tablo) tüm varlıklarım Serializable'ı uygulamadı.

Ancak etki alanı modeli daha karmaşık hale geldiğinde, varlıklarımdan birinin Serializable'ı uygulamadığını söyleyen RuntimeException aldım.

Hibernate'i bir JPA uygulaması olarak kullanıyorum.

Merak ediyorum:

  1. Satıcıya özgü gereksinim / davranış mı?
  2. Serileştirilebilir varlıklarıma ne olur? Saklama için mi yoksa transfer etmek için mi seri hale getirilebilirler?
  3. Varlığımı serileştirilebilir hale getirmek hangi anda gerekli hale gelir?

Yanıtlar:


59

Bu genellikle HQL ve yerel SQL sorgularını karıştırırsanız gerçekleşir. HQL'de Hibernate, aktardığınız türleri DB'nin anladığına göre eşler. Yerel SQL'i çalıştırdığınızda, eşlemeyi kendiniz yapmanız gerekir. Bunu yapmazsanız, varsayılan eşleme parametreyi serileştirmek ve veritabanına göndermektir (umarız anlar).


Bu, neden sadece "belki nasıl" olduğunu
açıklamıyor Bozho'nun

bu, varlığın serileştirilebilir arabirim uygulanmadan DB'ye kaydedileceği anlamına mı geliyor?
Hanumantha_3048092

@ Hanumantha_3048092 Evet. Varlık haritalama ve Serializableiki farklı kavramdır.
Aaron Digulla

@AaronDigulla Lütfen bunu bir örnek veya sözde kodla açıklar mısınız?
sdindiver

112

JPA Spesifikasyonuna göre:

Bir varlık örneği, değer tarafından ayrılmış bir nesne olarak (örneğin, bir uzak arabirim aracılığıyla) aktarılacaksa, varlık sınıfı Serileştirilebilir arabirimi uygulamalıdır.

"JSR 220: Enterprise JavaBeansTM, Sürüm 3.0 Java Persistence API Sürüm 3.0, Son Sürüm 2 Mayıs 2006"


15
(+1) Spesifikasyona bakmak her zaman verimli
Bozho

21
Bunun neden bu kadar çok olumlu oyu olduğunu anlamıyorum. OP, model daha basit olduğunda gerekli olmadığını söylüyor. Nesnelerin Java serileştirme yoluyla uzaktan gönderilmesi, nesnelerin karmaşıklığına bakılmaksızın DAİMA Serileştirilebilir olmasını gerektirir. Açıkçası bu OP'nin kullanım durumu değil.
Robin

Hazırda bekletme konusunda pek emin değilim, ancak diğer JPA sağlayıcılarında, sağlayıcının bir varlığın (nesnenin) bir kopyasını oluşturmasını gerektiren işlemler var. Serializablebu konuda yardımcı olabilir ve ısrar bağlamında Cloneableörneğin daha tutarlı olabilir .
JimmyB

Bu cevap sadece bir bilgi dökümüdür ve birisinin nedenini anlamasına hiç yardımcı olmaz.
chrips

62

Varlıklarınızı, Serializablekablo üzerinden aktarmanız (başka bir temsile serileştirmeniz), http oturumunda depolamanız (bu da servlet konteyneri tarafından sabit diske serileştirilir) vb.

Sadece ısrar uğruna Serializable, en azından Hazırda Bekletme ile gerekli değildir. Ancak bunları yapmak en iyi uygulamadır Serializable.


2
Bilmiyorum, belki varlıklarım örtük bir yere aktarılıyor. Hazırda bekletme + spring + jsf ve Tomcat kullanıyorum. Bu zincirde transfer nerede gerçekleşebilir?
Roman

@Roman, örneğin mevcut kullanıcı (bir varlık olabilir) ve tüm ilgili varlıkları oturumda sona erebilir, Bozho'nun dediği gibi servlet konteyneri tarafından diske serileştirilebilir.
OrangeDog

BU, "neden ve ne zaman" en iyi yanıttır! Açık! Teşekkür ederim
chrips

15

Göre hazırda docs @JoinColumn ek açıklama kullanırken,:

Adında bir parametre daha var referencedColumnName. Bu parametre, birleştirmede kullanılacak olan hedeflenen varlıktaki sütunu bildirir. Not kullanıldığında bu referencedColumnNameolmayan bir birincil anahtar kolona, ilgili sınıfı olmak zorundadır Serializable.


11

JPA spesifikasyonu

JPA spesifikasyonuna göre, bir kuruluş Serializableyalnızca bir JVM'den diğerine aktarılması gerekiyorsa veya varlık EJB konteyneri tarafından pasifleştirilmesi gereken bir Durum Bilgili Session Bean tarafından kullanılıyorsa uygulamalıdır.

Bir varlık örneği, değer tarafından ayrılmış bir nesne olarak (örneğin, bir uzak arabirim aracılığıyla) aktarılacaksa, varlık sınıfı Serializablearabirimi uygulamalıdır .

Hazırda beklet

Hazırda bekletme, yalnızca varlık özniteliklerinin olmasını gerektirir Serializable, ancak varlığın kendisi değildir.

Bununla birlikte, JPA spesifikasyonu uygulandığında, Serializabletüzel kişilere ilişkin tüm JPA gereksinimleri Hibernate için de geçerlidir.

Tomcat

Tomcat belgelerine göre , HttpSessionözniteliklerin de şunlar olması gerekir Serializable:

Apache Tomcat normal bir şekilde kapatıldığında ve yeniden başlatıldığında veya bir uygulama yeniden yüklemesi tetiklendiğinde, standart Yönetici uygulaması, şu anda etkin olan tüm oturumları yol adı özelliği aracılığıyla bulunan bir disk dosyasına serileştirmeye çalışır. Bu tür kaydedilen tüm oturumlar daha sonra serileştirilir ve uygulamanın yeniden yüklenmesi tamamlandığında etkinleştirilir (ortalama süre içinde sürelerinin dolmadığı varsayılarak).

Oturum özniteliklerinin durumunu başarıyla geri yüklemek için, bu tür tüm özniteliklerin java.io.Serializable arabirimini uygulaması ZORUNLUdur.

Dolayısıyla, varlık içinde depolanıyorsa HttpSession, uygulaması gerekir Serializable.


8

JSR-317 spesifikasyonlarına atıfta bulunan Conor'un güzel cevabını tamamlamak için. Tipik olarak, EAR projeleri, uzak arabirim aracılığıyla EJB'lerin açığa çıktığı bir EJB modülünden oluşur. Bu durumda, varlık çekirdeklerinizi uzak EJB'de toplandıklarından ve ağ üzerinden kablolanacak şekilde oluşturulduklarından serileştirilebilir hale getirmeniz gerekir.

CDI'sız bir JEE6 savaş projesi: serileştirilemeyen JPA varlıkları tarafından desteklenen EJB lite içerebilir.

CDI ile bir JEE6 savaş projesi: Oturum, uygulama veya konuşma kapsamını kullanan fasulye serileştirilebilir olmalıdır, ancak istek kapsamını kullanan fasulyelerin serileştirilebilir olması gerekmez. Bu nedenle, temeldeki JPA varlığı fasulye - varsa - aynı semantiği takip eder.


7

Sadece sebattan bahsedersek, Serializablegerekli değildir Ama varlıkları yapmak en iyi uygulamadır Serializable.

Biz teşhir varsa domain/ entitiesdoğrudan kullanmak yerine, sunum katmanına maruz nesnelerin DTObiz uygulamak gerekir Bu durumda, Serializable. Bu etki alanı nesneleri, HTTPSessionönbelleğe alma / optimizasyon amacıyla depolanabilir . Bir http oturumu serileştirilebilir veya kümelenebilir. Ve aynı zamanda JVMörnekler arasında veri aktarımı için de gereklidir .

DTOKalıcılık katmanını ve hizmet katmanını ayırmak için kullandığımızda , etki alanı nesnelerini Serializableters üretken olarak işaretlemek ve " encapsulation" kuralını ihlal eder . Sonra bir anti-model haline gelir.

Bileşik tanımlayıcılar

Birincil anahtar sınıfı serileştirilebilir olmalıdır.

POJO Modelleri

Bir varlık örneği uzaktan ayrılmış bir nesne olarak kullanılacaksa, varlık sınıfı Serializablearabirimi uygulamalıdır .

Önbellek
Ek olarak, clusteredikinci bir seviye uyguluyorsanız cache, varlıklarınızın olması gerekir serializable. Tanımlayıcı, ikinci düzey bir önbellek girişi için anahtar olarak kullanılabileceğinden, Serializablebu bir JPA gereksinimi identifierolduğu için olmalıdır.

Ve varlıkları serileştirdiğimizde serialVersionUID, özel erişim değiştiriciyle açıkça sağladığınızdan emin olun . Çünkü bir serializablesınıf açıkça a bildirmezse serialVersionUID, serileştirme çalışma zamanı, serialVersionUIDJava (TM) Nesne Serileştirme Spesifikasyonu'nda açıklandığı gibi, sınıfın çeşitli yönlerine göre bu sınıf için varsayılan bir değer hesaplayacaktır . Varsayılan serialVersionUIDhesaplama, derleyici uygulamalarına bağlı olarak değişebilen sınıf ayrıntılarına karşı oldukça hassastır ve bu nedenle InvalidClassExceptionsseriyi kaldırma sırasında beklenmedik sonuçlara neden olabilir .


6

Sorunun, açıklamasız karmaşık tipte (sınıf) bir alana sahip olmakla ilgili olduğuna inanıyorum. Bu gibi durumlarda, varsayılan işlem, nesneyi veritabanında serileştirilmiş biçiminde depolamak olacaktır (muhtemelen yapmak istediğiniz şey bu değildir) Örnek:

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

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

Yukarıdaki durumda, CustomerData, serileştirilmiş formunda veritabanındaki bir bayt dizisi alanına kaydedilecektir.


5

Onları serileştirmek istiyorsanız, sınıflar Serializable uygulamalıdır. Bu, doğrudan JPA ile ilgili değildir ve JPA belirtimi, varlıkların serileştirilebilir olmasını gerektirmez. Hibernate bundan gerçekten şikayet ediyorsa, bunun bir Hazırda Bekletme hatası olduğunu varsayıyorum, ancak varlıklarla doğrudan veya dolaylı olarak serileştirilebilir olmalarını gerektiren başka bir şey yaptığınızı varsayıyorum.


3

Lütfen http://www.adam-bien.com/roller/abien/entry/do_jpa_entities_have_to adresine bakın , java.io.Serializable uygulamasının JVM örnekleri arasında IIOP veya JRMP (RMI) aracılığıyla veri aktarımı için gereklidir. Saf bir web uygulaması durumunda, etki alanı nesneleri bazen önbelleğe alma / optimizasyon amacıyla HTTPSession'da depolanır. Bir http oturumu serileştirilebilir (pasifleştirme) veya kümelenebilir. Her iki durumda da tüm içeriğin Seri hale getirilebilir olması gerekir.


1

postman veya ajax veya açısal js vb. kullanarak uzaktan isabet ....., Jackson fastxml ile StackOverflow istisnası ile tekrar döngüsüne neden olabilir. Bu nedenle, serileştirici kullanmak daha iyidir.


1
  1. Varlığımı serileştirilebilir hale getirmek hangi anda gerekli hale gelir?

Ehcache'yi ikinci seviye önbellek olarak disk deposu ile uygulamak (yani @Cacheablevarlık veya havuz / hizmet yöntemi üzerinde açıklama kullanmak ) Serializable gerektirir, aksi takdirde önbellek NotSerializableExceptionvarlığı disk önbelleğine yazmak için başarısız olur ( ).


0

Bu aynı zamanda yanlış yazılmış bir kimliği ikinci parametre olarak em.find () gibi bir şeye geçirdiğinizde (yani kimliğinden ziyade varlığın kendisini ilettiğinizde) ortaya çıkan hatadır. Henüz JPA varlıklarını serileştirilebilir olarak bildirmeyi gerekli bulmadım - aman tarafından açıklandığı gibi referencedColumnName kullanmıyorsanız bu gerçekten gerekli değil.


0

JPA varlıkları uzak EJB işlemleri tarafından parametre veya dönüş değerleri olarak kullanıldığında

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.