Hazırda Bekletme Açıklamaları - Hangisi daha iyi, alan veya mülk erişimi?


Yanıtlar:


33

İhtiyacım olduğunda erişimcilerime iş mantığı ekleyebileceğim için erişimcileri tercih ederim. İşte bir örnek:

@Entity
public class Person {

  @Column("nickName")
  public String getNickName(){
     if(this.name != null) return generateFunnyNick(this.name);
     else return "John Doe";
  }
}

Ayrıca, karışıma başka bir libs atıyorsanız (bazı JSON dönüştüren lib veya BeanMapper veya Dozer veya alıcı / ayarlayıcı özelliklerine dayalı diğer fasulye haritalama / klonlama lib gibi), lib'in kalıcılıkla senkronize olduğunu garanti edersiniz yöneticisi (her ikisi de alıcı / ayarlayıcı kullanın).


17
Bunun ORM'in uygulama kodunuza değil alanlarınıza / özelliklerinize nasıl eriştiği ile ilgili olduğuna dikkat edin. Alan erişimi ile getNickName () yönteminiz tam olarak beklediğiniz gibi çalışır. Alıcılar / ayarlayıcıların dışında kalıcı 'özellikler' kullanırsanız aynı şey geçerli değildir. Burada, mülk erişimi ve tembel yükleme ile ilgili sorunlara vurabilirsiniz. Yani hayır, genel olarak bu argümana katılmıyorum. Ancak, Hibernate'i son kontrol ettiğimde @Id alanlarının saha erişimiyle ilgili sorunlar vardı.
Rob Bygrave

11
bu cevap soru ile ilgili değildir. Duffymo tarafından en iyi cevap
Janning

9
erişimcilerin içinde herhangi bir iş mantığı olmamalıdır. bu açık bir davranış değil.
iuriisusuk

Bu yanıt işareti neden doğru? Alanı eşleştirebileceğiniz ve aynı şekilde bir ayarlayıcı / alıcı sağlayabileceğiniz doğru değildir.
Lucke

246

Her ikisi için de argümanlar vardır, ancak bunların çoğu "kullanıcı için mantık eklemeniz gerekiyorsa" veya "xxxx enkapsülasyonu keser" gibi belirli kullanıcı gereksinimlerinden kaynaklanır. Bununla birlikte, kimse teori hakkında gerçekten yorum yapmadı ve uygun bir şekilde gerekçelendirildi.

Hazırda Beklet / JPA bir nesneyi sürdürdüğünde gerçekte ne yapar - şey, nesnenin DEVLETİNİ devam ettirir. Bu, kolayca çoğaltılabilecek şekilde saklanması anlamına gelir.

Kapsülleme nedir? Kapsülleme, verilerin (veya durumun) uygulamanın / istemcinin verilere güvenli bir şekilde erişmek için kullanabileceği bir arayüzle kapsüllenmesi anlamına gelir - tutarlı ve geçerli tutar.

Bunu MS Word gibi düşünün. MS Word bellekte belgenin bir modelini (STATE belgeleri) korur. Kullanıcının belgeyi değiştirmek için kullanabileceği bir arabirim sunar - bir dizi düğme, araç, klavye komutları vb. Ancak, bu belgeyi sürdürmeyi (Kaydetmeyi) seçtiğinizde, tuş basışı kümesini değil dahili durumu kaydeder ve fare tıklamaları oluşturmak için kullanılır.

Nesnenin dahili durumunu kaydetmek kapsüllemeyi KESİNMEZ - aksi takdirde kapsüllemenin ne anlama geldiğini ve neden var olduğunu gerçekten anlamıyorsunuz. Gerçekten nesne serileştirmesi gibidir.

Bu nedenle, ÇOK DURUMDA, AKSESUARLAR yerine ALANLARA devam etmek uygundur. Bu, bir nesnenin tam olarak depolandığı şekilde veritabanından yeniden oluşturulabileceği anlamına gelir. Herhangi bir validasyona gerek yoktur, çünkü bu orijinalin yaratıldığı zaman ve veritabanında saklanmadan önce yapıldı (Tanrı yasakladığı sürece, DB'de geçersiz veriler depolamıyorsunuz !!!!). Benzer şekilde, nesne saklanmadan önce hesaplandıkları için değerlerin hesaplanmasına gerek yoktur. Nesne kaydedilmeden önceki gibi görünmelidir. Aslında, alıcılara / ayarlayıcılara ek şeyler ekleyerek , orijinalin tam bir kopyası olmayan bir şeyi yeniden oluşturma riskinizi artırabilirsiniz .

Tabii ki, bu işlevsellik bir nedenden dolayı eklenmiştir. Erişimcileri devam ettirmek için bazı geçerli kullanım durumları olabilir, ancak bunlar tipik olarak nadirdir. Bir örnek, hesaplanan bir değerin devam etmesini önlemek isteyebilir, ancak değerin alıcısında neden talep üzerine hesaplayamadığınızı sormak veya alıcıda tembel bir şekilde başlatmak istemeyebilirsiniz. Şahsen iyi bir kullanım durumu düşünemiyorum ve buradaki cevapların hiçbiri gerçekten bir "Yazılım Mühendisliği" yanıtı vermiyor.


9
Yazılım mühendisliği yanıtı: erişimcilerin kullanılması DRY'yi ihlal ediyor.
sourcedelica

1
@Martin Cevabınızın son paragrafına ilişkin bir takip sorum var. "Bir örnek, hesaplanan değerin devam etmesini önlemek olabilir" yazdınız. Mülke dayalı erişime sahip olarak hesaplanan değere devam etmeyi nasıl önleyebilirsiniz? Bunu yapmamayı tartıştığını biliyorum ama burada bir noktaya değiniyorum. Açıklayabilir misin?
Geek

4
@Geek Şimdi geri okuduğumdan kendimden tam olarak emin değilim. Bu cevabı yazmamın üzerinden iki yıl geçti. Sanırım daha iyi bir örnek eski bir veritabanı ile çalışıyor olabilir ve veri nesne modelinize farklı bir şekilde sunulur - erişimciler ikisi arasında bir eşleme sağlayabilir.
Martin

23
Erişimcileri eşlemek için iyi bir kullanım durumu, herhangi bir kalıcılık uygulamasına bağlı olmayan üçüncü taraf varlık sınıflarının alt sınıflarına eşleme bilgisi eklemeniz gerektiğidir. Bu sınıflardaki alanlar özel olduğundan, erişimcileri geçersiz kılmalı ve bunlara eşleme ek açıklamaları eklemelisiniz. Başka bir seçenek XML eşlemesi kullanmak olabilir, ancak bazı şeyleri orada yapmak çok zordur. Ek açıklama almak ve üçüncü taraf sınıflarını eşlemek istiyorsanız, bunları alt sınıflara ayırmak ve erişimcilere ek açıklama eklemek ek yoldur.
Elnur Abdurrakhimov

5
@ElnurAbdurrakhimov oraya gidiyoruz, mükemmel bir örnek. Teşekkürler.
Martin

79

Ben alan erişimi tercih, çünkü bu şekilde her özellik için alıcı / ayarlayıcı sağlamak zorunda değilim.

Google aracılığıyla yapılan hızlı bir anket, saha erişiminin çoğunluk olduğunu gösteriyor (ör. Http://java.dzone.com/tips/12-feb-jpa-20-why-accesstype . ).

Alan erişiminin Spring tarafından önerilen deyim olduğuna inanıyorum, ancak bunu destekleyecek bir referans bulamıyorum.

Bir var , ilgili SO soru performansını ölçmek için çalıştı ve "hayır fark var" sonucuna vardı.


varlık ayarlayıcı getter sağlamazsanız o zaman bu alanın kullanımı nedir ... uygulamada herhangi bir yerde kullanamazsınız, alanlar özel olduğundan
anshulkatta

1
Alanlarınız için kötü bir alıcı ve ayarlayıcı sağlamıyor mu ?, Sanırım buradaki yorumum her zaman doğru değil, çünkü kamuya açık bir alan kabul ediyordum, oysa asla erişilemeyen özel bir alan olabilir.
Mathijs Segers

3
@anshulkatta Sorularınızı gerçekten ele almam gerektiğini hissediyorum, çünkü kapsüllemenin konusu bu. İdeal olarak, tüm alanlarınız özel olmalı ve mümkünse alıcıları veya ayarlayıcıları olmamalıdır - bu, umabileceğiniz en iyi kapsülleme düzeyidir. Bir parola denetleyicisi düşünün. 2 özel alan şifresiHash ve failAttempts. Her ikisi de özel veya alıcı olmadan özel olabilir. Bunlar, karma, passwordHash'a karşı kontrol eden ve ardından başarısız olan bool checkPassword (string password) tarafından kullanılır. Bu iki alana erişmek için başka kodlara gerek yoktur.
Martin

2
@anshulkatta, OOP'de alıcıların ve ayarlayıcıların bir anti-desen olduğu, prosedürel programlamadan geldikleri, onlarla bir sınıfın kapsülleme ilkesini ihlal ettiği ve çok sayıda kazan plakası kodu ürettikleri, yani aynı tür kod tekrar tekrar tekrarlandı. Nesneler değişmez olmalıdır, eğer özelliklerinde değişiklik yapılması gerekiyorsa, sadece mülkün değerini döndürmekten daha fazlasını yapan bir yöntemle yapılmalıdır.
Uriel Arvizu

Öyle değil. Bu durumda "Anti-pattern" bir dogma meselesidir, dogma değil. Bununla birlikte, saha erişimi hala tercih edilmektedir. Daha iyi bir fikir ORM çözümlerinden tamamen uzaklaşmaktır. Uygun SQL yazmayı öğrenin.
duffymo

38

İşte emlak erişimcilerini kullanmak zorunda olduğunuz bir durum. 8 somut alt sınıfa miras almak için birçok uygulama iyiliği olan bir GENERIC özet sınıfınız olduğunu düşünün:

public abstract class Foo<T extends Bar> {

    T oneThing;
    T anotherThing;

    // getters and setters ommited for brevity

    // Lots and lots of implementation regarding oneThing and anotherThing here
 }

Şimdi bu sınıfa nasıl açıklama eklemelisiniz? Cevap, bu noktada hedef varlığı belirleyemediğiniz için alan veya mülk erişimi ile hiçbir şekilde açıklama ekleyemeyeceğinizdir. Somut uygulamalara açıklama eklemeniz GEREKİR. Ancak kalıcı özellikler bu üst sınıfta bildirildiğinden, alt sınıflarda özellik erişimini KULLANMALISINIZ.

Soyut genel süper sınıfları olan bir uygulamada alan erişimi bir seçenek değildir.


2
tuşe. Bunu düşünmemiştim. Eminim Hibernate bunlar için çılgın bir sql ortaya çıkarır.
Joseph Lust

8
Bu sorun, ek açıklama özellikleri olmadan mekanik olarak çözülmesi zor geliyor, ancak ben de devam etmek istediğim çok fazla uygulama içeren soyut bir genel sınıfa ihtiyaç duyduğum bir durumla karşılaşmadım. Tipik olarak nesnemi polimorfik yapmak için bir sınıf hiyerarşisi yaratırım (ki bu onu genel bir tür kırılma yapar) ve sadece kodun yeniden kullanımı için değil. Ve "çok ve çok sayıda uygulama" çoğu zaman SRP'yi zaten ihlal ediyor, bu durumda muhtemelen ayrı sınıflara taşıyacağım. Bu kullanım durumunu daha açık hale getiren somut bir örnek var mı?
Merlyn Morgan-Graham

Sahip olduğum tek somut örnek, 500 karakterlik bir yorumda tarif edemediğim uygulamam ;-)
HDave

3
Sen kullanabilirsiniz abstract T getOneThing()ve abstract void setOneThing(T thing)ve saha erişimini kullanabilir.
Arturo Volpe

33

Mülk erişimcilerini tercih etme ve kullanma eğilimindeyim:

  • İhtiyaç ortaya çıkarsa mantık ekleyebilirim (kabul edilen cevapta belirtildiği gibi).
  • foo.getId() bir proxy başlatmadan aramamı sağlar (Hazırda Beklet'i kullanırken, HHH-3718 çözülene kadar önemlidir ).

dezavantajı:

  • kodu daha az okunabilir yapar, örneğin, orada olup olmadığını görmek için bir sınıfa göz atmanız gerekir @Transient.

ancak "proxy'leri" olmayan bir JPA sağlayıcısı kullanıyorsanız "JPA sağlayıcınız size empoze ediyor" diye bir sorun yaşamazsınız.
Neil Stockton

13

Bu gerçekten belirli bir duruma bağlıdır - her iki seçenek de bir nedenle kullanılabilir. IMO üç vakaya kadar kaynar:

  1. setter, bir veritabanından örnek yüklenirken yürütülmemesi gereken bir mantığa sahiptir; örneğin, ayarlayıcıda bazı değer doğrulamaları gerçekleşir, ancak db'den gelen veriler geçerli olmalıdır (aksi takdirde oraya ulaşmaz (:); bu durumda alan erişimi en uygunudur;
  2. setter, db'den bir örneğin yüklenmesi sırasında bile her zaman çağrılması gereken bir mantığa sahiptir; örneğin, başlatılan mülk, hesaplanan bazı alanların hesaplanmasında kullanılır (örneğin, özellik - parasal bir tutar, hesaplanan özellik - aynı örneğin birkaç parasal özelliğinin toplamı); bu durumda mülk erişimi gerekir.
  3. Yukarıdaki durumların hiçbiri - o zaman her iki seçenek de geçerlidir, sadece tutarlı kalın (ei alan erişimi bu durumda seçim ise, benzer durumda her zaman kullanın).

Hazırda Bekletme konusunda yeniyim ve aynı soru ile mücadele ediyorum. Bence bu yazı en açık cevabı veriyor. Teşekkür ederim.
Sam Levin

12

Ayarlayıcılarda sadece değeri ayarlamaktan daha fazla bir şey yapmak istiyorsanız, alan erişimi ve NOT eklentileri (özellik erişimi) şiddetle tavsiye ediyorum (örn. Şifreleme veya hesaplama).

Özellik erişimindeki sorun, nesne yüklendiğinde ayarlayıcıların da çağrılmasıdır. Şifrelemeyi tanıtmak isteyene kadar bu benim için aylarca işe yaradı. Kullanım durumumuzda ayarlayıcıdaki bir alanı şifrelemek ve alıcıda şifresini çözmek istedik. Özellik erişimiyle ilgili sorun, Hazırda Bekletme nesneyi yüklediğinde, alanı doldurmak için ayarlayıcıyı çağırdığı ve böylece şifrelenmiş değeri tekrar şifrelediği idi. Bu yazı ayrıca şunu da belirtir: Java Hazırda Bekletme: Kimi çağırdığına bağlı olarak farklı özellik kümesi işlev davranışı

Bu, saha erişimi ile mülk erişimi arasındaki farkı hatırlayana kadar başım ağrıyor. Şimdi tüm ek açıklamalarımı mülk erişiminden saha erişimine taşıdım ve şimdi iyi çalışıyor.


Evet - Özellik erişimini kullanırsanız, ayarlayıcıda alan değerini ayarlamanın dışında hiçbir şey yapamayacağınızı gördüm.
HDave

2
+1 Alıcılardan / ayarlayıcılardan uzak durun. Kullandığım projectlombok.org ve geliştiriciler gizli tutun.
bhantol

11

Saha erişimini aşağıdaki nedenlerle kullanmayı tercih ederim:

  1. Mülkiyet erişim eşittir / hashCode uygulanması ve zaman çok kötü hatalar yol açabilir doğrudan alanlara başvuran (kendi alıcılar aracılığıyla aksine). Bunun nedeni, proxy'nin yalnızca alıcılara erişildiğinde başlatılması ve doğrudan alan erişiminin null değerini döndürmesidir.

  2. Mülkiyet erişim tüm açıklama gerektirir yarar yöntemleri olarak (örneğin addChild / removeChild) @Transient.

  3. Alan erişimi sayesinde, alıcıyı göstermeyecek şekilde @ Sürüm alanını gizleyebiliriz. Bir alıcı da bir ayarlayıcı eklemeye yol açabilir ve versionalan asla manuel olarak ayarlanmamalıdır (bu çok kötü sorunlara yol açabilir). Tüm sürüm artışı, OPTIMISTIC_FORCE_INCREMENT veya PESSIMISTIC_FORCE_INCREMENT açık kilitleme yoluyla tetiklenmelidir .


1. Saha erişim stratejisi bunu nasıl önler? Bu, erişim stiline bakılmaksızın vekillerle ilgili genel bir tuzak gibi görünüyor. 2. Emin misiniz, sadece yardımcı alıcılar olmalı? (ama yine de iyi bir argüman). 3.version Alan için erişimcilerin teşhir edilmesi, müstakil varlıklar yerine DTO'ların kullanıldığı durumlarda genellikle yararlıdır.
Dragan Bozanovic

1. Proxy başlatıldığı için. 2.% 100 emin. 3. Bu geçerli bir nokta.
Vlad Mihalcea

Cehaletimi ve olası metin yorumlama eksikliğini affedin, (ben anadili İngilizce değilim). Sadece açıklığa kavuşturmak için, alan erişimi alıcı / ayarlayıcı yöntemlerine ihtiyaç duyulmadığı zamandır, bu yüzden bütüncül bir POJO için alanlar kamuya açık mı? Ama ilk konuda bir şeyler söylüyorsunuz ve bağlantılı blog yazısı bunun tersini söylüyor. Anladığım şey, proxy'leri ve alan erişimini kullanırken eşit kullanamamanızdı.
MaikoID

Hayır. Alan erişimi Hibernate öğesinin varlık niteliklerini okumak için yansımalar aracılığıyla kullandığı anlamına gelir. Daha fazla ayrıntı için, Hazırda Bekletme Kullanıcı Kılavuzu'ndaki Erişim Türü bölümüne bakın .
Vlad Mihalcea

7

Ben ORM bunu yaparsanız bile, alanların güncellenmesi doğrudan kapsülleme tatili nedeniyle özelliği ek açıklama daha iyi olduğunu düşünüyorum.

İşte sizi nerede yakacağına dair harika bir örnek: muhtemelen hazırda bekletme doğrulayıcısı ve kalıcılığı için ek açıklamalarınızı aynı yerde (alanlar veya özellikler) istersiniz. Bir alana eklenmiş olan hazırda bekletme modundan onay alan destekli doğrulamalarınızı test etmek istiyorsanız, birim testinizi yalnızca doğrulayıcıya ayırmak için kuruluşunuzun bir kısmını kullanamazsınız. Ahh.


2
Bu yüzden erişimcilere doğrulayıcı ek açıklamaları ve alanlara kalıcılık ek açıklamaları koydunuz
kılçık

6

Tembel başlatma konusunda mülk erişimi ve alan erişimi arasında oldukça farklı olduğuna inanıyorum.

2 temel fasulye için aşağıdaki eşlemeleri göz önünde bulundurun:

<hibernate-mapping package="org.nkl.model" default-access="field">
  <class name="FieldBean" table="FIELD_BEAN">
    <id name="id">
      <generator class="sequence" />
    </id>
    <property name="message" />
  </class>
</hibernate-mapping>

<hibernate-mapping package="org.nkl.model" default-access="property">
  <class name="PropBean" table="PROP_BEAN">
    <id name="id">
      <generator class="sequence" />
    </id>
    <property name="message" />
  </class>
</hibernate-mapping>

Ve aşağıdaki birim testleri:

@Test
public void testFieldBean() {
    Session session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction();
    FieldBean fb = new FieldBean("field");
    Long id = (Long) session.save(fb);
    tx.commit();
    session.close();

    session = sessionFactory.openSession();
    tx = session.beginTransaction();
    fb = (FieldBean) session.load(FieldBean.class, id);
    System.out.println(fb.getId());
    tx.commit();
    session.close();
}

@Test
public void testPropBean() {
    Session session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction();
    PropBean pb = new PropBean("prop");
    Long id = (Long) session.save(pb);
    tx.commit();
    session.close();

    session = sessionFactory.openSession();
    tx = session.beginTransaction();
    pb = (PropBean) session.load(PropBean.class, id);
    System.out.println(pb.getId());
    tx.commit();
    session.close();
}

Gerekli seçimlerdeki ince farkı göreceksiniz:

Hibernate: 
    call next value for hibernate_sequence
Hibernate: 
    insert 
    into
        FIELD_BEAN
        (message, id) 
    values
        (?, ?)
Hibernate: 
    select
        fieldbean0_.id as id1_0_,
        fieldbean0_.message as message1_0_ 
    from
        FIELD_BEAN fieldbean0_ 
    where
        fieldbean0_.id=?
0
Hibernate: 
    call next value for hibernate_sequence
Hibernate: 
    insert 
    into
        PROP_BEAN
        (message, id) 
    values
        (?, ?)
1

Yani, arama fb.getId()bir seçim gerektirir, oysa pb.getId()istemez.


Bu komik! :) Ama bu uygulamaya özgü bir davranış, eminim. I
Vladimir Dyuzhev

Evet, sanırım bunun nedeni sadece kalıcı sınıfların araçsal olması. Ancak bu bir pitty çünkü kimlik alanı genellikle iş değeri olmayan ve herhangi bir erişimciye ihtiyaç duymayan tek alandır.
Maurice Perry

6

Alan tabanlı erişimi seçmenin en önemli nedenlerini özetlemeye çalışayım. Daha derinlemesine dalmak istiyorsanız lütfen blogumdaki şu makaleyi okuyun: JPA ve Hibernate'de Erişim Stratejileri - Hangisi daha iyi, alan veya mülk erişimi?

Alan tabanlı erişim çok daha iyi bir seçenektir. İşte 5 nedeni:

Sebep 1: Kodunuzun daha iyi okunabilirliği

Alan tabanlı erişim kullanıyorsanız, varlık özelliklerinize eşleme ek açıklamalarınızla açıklama eklersiniz. Tüm varlık özniteliklerinin tanımını sınıfınızın en üstüne yerleştirerek, tüm özniteliklerin ve eşlemelerinin nispeten küçük bir görünümünü elde edersiniz.

Sebep 2: Başvurunuz tarafından çağrılmaması gereken alıcı veya ayarlayıcı yöntemlerini atlayın

Alan tabanlı erişimin bir diğer avantajı, kalıcılık sağlayıcınızın (örneğin, Hazırda Bekletme veya EclipseLink) varlık özelliklerinizin alıcı ve ayarlayıcı yöntemlerini kullanmamasıdır. Bu, işletme kodunuz tarafından kullanılmaması gereken herhangi bir yöntem sağlamanız gerekmediği anlamına gelir. Bu çoğunlukla, oluşturulan birincil anahtar niteliklerinin veya sürüm sütunlarının ayarlayıcı yöntemleri için geçerlidir . Kalıcılık sağlayıcınız bu niteliklerin değerlerini yönetir ve bunları programlı olarak ayarlamamanız gerekir.

Sebep 3: Alıcı ve ayarlayıcı yöntemlerinin esnek uygulanması

Kalıcı sağlayıcınız alıcı ve ayarlayıcı yöntemlerini çağırmadığından, herhangi bir dış gereksinimi yerine getirmek zorunda değildir. Bu yöntemleri istediğiniz şekilde uygulayabilirsiniz. Bu, işletmeye özgü doğrulama kuralları uygulamanızı, ek iş mantığını tetiklemenizi veya varlık özelliğini farklı bir veri türüne dönüştürmenizi sağlar.

Örneğin, bunu isteğe bağlı bir ilişkilendirmeyi veya özniteliği bir Java'ya sarmak için kullanabilirsiniz .Optional

Sebep 4: Fayda yöntemlerini @Transient

Alan tabanlı erişim stratejisinin bir diğer yararı da, yardımcı yöntemlerinize açıklama eklemenize gerek olmamasıdır @Transient. Bu ek açıklama, kalıcılık sağlayıcınıza bir yöntemin veya niteliğin varlık kalıcı durumunun bir parçası olmadığını bildirir. Ve alan tipi erişim ile kalıcı durum varlığınızın nitelikleri tarafından tanımlandığından, JPA uygulamanız varlığınızın tüm yöntemlerini yok sayar.

Sebep 5: Proxy'lerle çalışırken hatalardan kaçının

Hazırda Beklet, tembel olarak bire birleştirilmiş dernekler için proxy kullanır, böylece bu derneklerin başlatılmasını kontrol edebilir. Bu yaklaşım neredeyse tüm durumlarda işe yarar. Ancak mülke dayalı erişim kullanırsanız tehlikeli bir tuzak ortaya çıkarır.

Özellik tabanlı erişim kullanıyorsanız, Hazırda Beklet, getter yöntemini çağırdığınızda proxy nesnesinin niteliklerini başlatır. İş kodunuzda proxy nesnesini kullanıyorsanız her zaman böyle olur. Ancak oldukça eşittir ve hashCode uygulamaları özniteliklere doğrudan erişir. Proxy özniteliklerinden herhangi birine ilk kez erişiyorsanız, bu öznitelikler yine de başlatılmaz.


3

Varsayılan olarak, JPA sağlayıcıları varlık alanlarının değerlerine erişir ve varlığın JavaBean özellik erişimcisi (alıcı) ve mutator (ayarlayıcı) yöntemlerini kullanarak bu alanları veritabanı sütunlarıyla eşleştirir. Bu nedenle, bir kuruluştaki özel alanların adları ve türleri JPA için önemli değildir. Bunun yerine, JPA yalnızca JavaBean özellik erişimcilerinin adlarına ve dönüş türlerine bakar. Bunu @javax.persistence.Access, JPA sağlayıcının kullanması gereken erişim yöntemini açıkça belirtmenizi sağlayan ek açıklamayı kullanarak değiştirebilirsiniz .

@Entity
@Access(AccessType.FIELD)
public class SomeEntity implements Serializable
{
...
}

AccessType enum için kullanılabilir seçenekler PROPERTY (varsayılan) ve FIELD'dir. PROPERTY ile, sağlayıcı JavaBean özellik yöntemlerini kullanarak alan değerlerini alır ve ayarlar. FIELD, sağlayıcının örnek alanlarını kullanarak alan değerlerini almasını ve ayarlamasını sağlar. En iyi uygulama olarak, varsayılana sadık kalmanız ve aksi takdirde zorlayıcı bir nedeniniz olmadıkça JavaBean özelliklerini kullanmanız gerekir.

Bu özellik ek açıklamalarını özel alanlara veya genel erişimci yöntemlerine koyabilirsiniz. AccessType.PROPERTYJavaBean erişimcileri yerine (varsayılan) kullanır ve özel alanlara açıklama eklerseniz , alan adlarının JavaBean özellik adlarıyla eşleşmesi gerekir. Ancak, JavaBean erişimcilerine ek açıklama eklerseniz adların eşleşmesi gerekmez. Benzer şekilde, AccessType.FIELDalanlar yerine JavaBean erişimcilerini kullanır ve ek açıklama eklerseniz , alan adlarının da JavaBean özellik adlarıyla eşleşmesi gerekir. Bu durumda, alanlara ek açıklama eklerseniz eşleşmeleri gerekmez. JavaBean erişimcilerinin AccessType.PROPERTYve alanlarının tutarlı olması ve açıklama eklenmesi en iyisidir AccessType.FIELD.

Aynı varlıktaki JPA özellik ek açıklamalarını ve JPA alan ek açıklamalarını asla karıştırmamanız önemlidir. Bunu yapmak belirtilmemiş davranışlarla sonuçlanır ve büyük olasılıkla hatalara neden olur.


2

Henüz varmadık mı

Bu eski bir sunumdur ancak Rod, mülk erişimine ilişkin ek açıklamaların anemik alan modellerini teşvik ettiğini ve ek açıklama için "varsayılan" yol olmaması gerektiğini önermektedir.


2

Alan erişimi lehine bir başka nokta, aksi takdirde koleksiyonerler için ayarlayıcıları açığa çıkarmak zorunda kalmanızdır, çünkü benim için, kalıcı toplama örneğini Hibernate tarafından yönetilmeyen bir nesneye değiştirmek, veri tutarlılığınızı kesinlikle kıracaktır.

Bu nedenle, varsayılan kurucudaki boş uygulamalara başlatılan korumalı alanlar olarak koleksiyonlara sahip olmayı ve yalnızca alıcılarını göstermeyi tercih ederim. Gibi Sonra, yalnızca yönetilen operasyonlar clear(), remove(), removeAll()vb değişikliklerin hazırda habersiz hale asla mümkündür.


Ayarlayıcılar korunabileceğinden hiçbir şeyi ortaya çıkarmak zorunda değilsiniz. Ayrıca bu ayarlayıcılar, arabirimin bir parçası değildir, bu yüzden halka açık olsalar bile, kolayca erişilemezler.
HDave

2

Tarlaları tercih ederim, ancak ek açıklamaları alıcılara yerleştirmeye zorlayan bir durumla karşılaştım.

Hazırda Bekletme JPA uygulamasıyla, @Embeddedalanlar üzerinde çalışmaz gibi görünüyor. Bu yüzden alıcıya gitmek zorunda. Ve bunu alıcıya koyduğunuzda, çeşitli @Columnek açıklamalar alıcılara da gitmelidir. (Sanırım Hibernate burada alanları ve alıcıları karıştırmak istemiyor.) Ve @Columnbir sınıfta alıcıları koyduğunuzda , muhtemelen bunu yapmak mantıklı.


2

Saha erişimcilerini destekliyorum. Kod çok daha temiz. Tüm ek açıklamalar bir sınıfın bir bölümüne yerleştirilebilir ve kodun okunması çok daha kolaydır.

Özellik erişimciler ile başka bir sorun buldum: Eğer sınıfta kalıcı özellikleri ile ilişkili olarak açıklanamayan getXYZ yöntemleri varsa, hazırda bekletme bazı özellikleri çok karmaşık hata iletileri ile sonuçlanan denemek için sql oluşturur. İki saat boşa gider. Bu kodu yazmadım; Geçmişte her zaman saha erişimcilerini kullandım ve bu sorunla hiç karşılaşmadım.

Bu uygulamada kullanılan hazırda bekleme sürümleri:

<!-- hibernate -->
<hibernate-core.version>3.3.2.GA</hibernate-core.version>
<hibernate-annotations.version>3.4.0.GA</hibernate-annotations.version>
<hibernate-commons-annotations.version>3.1.0.GA</hibernate-commons-annotations.version>
<hibernate-entitymanager.version>3.4.0.GA</hibernate-entitymanager.version>

2

Özellikler üzerinden erişim üzerinden alanlar üzerinden erişim seçmelisiniz. Alanlarla gönderilen ve alınan verileri sınırlayabilirsiniz. Via özellikleri ile bir ana bilgisayar olarak daha fazla veri gönderebilir ve G mezhepleri ayarlayabilirsiniz (hangi fabrika toplam özelliklerin çoğunu ayarlar).




1

Varlık fasulyeleri oluşturduk ve alıcı ek açıklamaları kullandık. Karşılaştığımız sorun şudur: bazı kuruluşlar, ne zaman güncellenebileceklerine ilişkin bazı özellikler için karmaşık kurallara sahiptir. Çözüm, her ayarlayıcıda, gerçek değerin değişip değişmediğini ve değişiyorsa değişikliğe izin verilip verilmeyeceğini belirleyen bir iş mantığına sahip olmaktı. Elbette, Hibernate her zaman özellikleri ayarlayabilir, böylece iki grup ayarlayıcı ile sonuçlandık. Oldukça çirkin.

Önceki yayınları okurken, varlık içerisindeki özelliklere başvurmanın, yüklenmeyen koleksiyonlarla ilgili sorunlara yol açabileceğini de görüyorum.

Sonuç olarak, gelecekte alanlara açıklama eklemek için eğilirdim.


0

Normalde fasulye POJO, bu yüzden zaten erişim var.

Yani soru "hangisi daha iyi?" Değil, basitçe "alan erişimi ne zaman kullanılır?". Ve cevap "alan için bir ayarlayıcı / alıcıya ihtiyaç duymadığınızda!".


4
Sorun, bir POJO'da alan erişimini ve mülk erişimini karıştıramamanız - bir tane seçmeniz gerekiyor
Martin OConnor

Gerçekten mi? Unutmuş olmalıyım. Her neyse, her zaman POJO ve d erişimcilerini kullanıyorum.
Vladimir Dyuzhev

JPA 2.0 ile (bu soru sorulduğunda etrafta yoktu) artık @AccessType ek açıklamasını kullanarak erişim türlerini karıştırabileceğinizi unutmayın.
mtpettyp

0

Bunu düşünüyorum ve yöntem aksesuarı seçiyorum

neden?

çünkü alan ve metot aksesuarı aynıdır ancak daha sonra yük alanında mantığa ihtiyacım olursa, alanlara yerleştirilen tüm notları taşıyorum

Saygılarımızla

Grubhart


0

Sınıflarınızı daha temiz hale getirmek için ek açıklamayı alana girin ve @Access (AccessType.PROPERTY) öğesini kullanın



0

AccessType.PROPERTY: EJB kalıcılık uygulaması, JavaBean "setter" yöntemleri aracılığıyla sınıfınıza durumu yükler ve JavaBean "getter" yöntemlerini kullanarak sınıfınızdan durum alır. Bu varsayılan ayardır.

AccessType.FIELD: Durum doğrudan sınıfınızın alanlarından yüklenir ve alınır. JavaBean "getters" ve "setters" yazmak zorunda değilsiniz.

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.