Анотації зі сплячки - Що краще, поле чи доступ до власності?


134

Це питання дещо пов’язане із запитанням про розміщення в сплячому режимі з анотацією .

Але я хочу знати, що краще ? Доступ через властивості чи доступ через поля? Які переваги та недоліки кожного?

Відповіді:


33

Я віддаю перевагу аксесуарам, оскільки можу додати деяку ділову логіку до своїх аксесуарів, коли мені потрібно. Ось приклад:

@Entity
public class Person {

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

Крім того, якщо ви кинете в суміш ще одну мочку (наприклад, яку-небудь конвертуючу JSON або BeanMapper, Dozer або іншу картографічну / картувальну базу на основі властивостей геттера / сеттера), ви отримаєте гарантію того, що ліб синхронізується зі стійкістю менеджер (обидва використовують getter / setter).


17
Зауважте, що мова йде про те, як ORM звертається до ваших полів / властивостей, а не до коду програми. З доступом до поля ваш метод getNickName () буде працювати точно так, як ви очікували. Це ж не вірно, якщо ви використовуєте стійкі "властивості" поза геттерам / сетерам. Саме тут ви можете зачепити проблеми з доступом до власності та ледачим завантаженням. Так ні, я не згоден з цим аргументом взагалі. Однак останній раз, коли я перевіряв, що в режимі Hibernate виникли проблеми з доступом до полів @Id на місцях.
Роб Біграйв

11
ця відповідь не пов'язана з питанням. Найкращою відповіддю комісіонка duffymo
Janning

9
не повинно бути жодної ділової логіки всередині аксесуарів. це не очевидно поведінка.
iuriisusuk

Чому цей знак відповіді є правильним? Це неправда, ви можете зіставити поле та надати йому сетер / геттер таким же чином.
Лукк

246

Існують аргументи для обох, але більшість з них випливає з певних вимог користувачів "що робити, якщо вам потрібно додати логіку для", або "xxxx порушує інкапсуляцію". Однак ніхто насправді ніхто не коментував цю теорію і не наводив належним чином аргументований аргумент.

Що насправді робить Hibernate / JPA, коли він зберігає об'єкт - добре, він зберігає СТАТЕЮ об’єкта. Це означає, що зберігати його можна таким чином, щоб його можна було легко відтворити.

Що таке інкапсуляція? Інкапсуляція означає інкапсуляцію даних (або стану) за допомогою інтерфейсу, який програма / клієнт може використовувати для безпечного доступу до даних - зберігаючи їх послідовні та дійсні.

Подумайте про це як MS Word. MS Word підтримує модель документа в пам'яті - документи ДЕРЖАВНІ. У ньому представлений інтерфейс, який користувач може використовувати для зміни документа - набір кнопок, інструментів, команд клавіатури тощо. Однак, коли ви вирішите зберегти (Зберегти) цей документ, він зберігає внутрішній стан, а не набір натискань клавіш і клацання миші, що використовується для його створення.

Збереження внутрішнього стану об'єкта НЕ порушує інкапсуляцію - інакше ви насправді не розумієте, що означає інкапсуляція та чому вона існує. Це насправді як об'єктна серіалізація.

З цієї причини В НАЙБІЛЬШИХ СЛУЧАХ доречно зберігати ПОЛІ, а не АКСЕСОРИ. Це означає, що об’єкт можна точно відтворити з бази даних саме таким чином, як він був збережений. Це не повинно потребувати ніякої перевірки, оскільки це робилося на оригіналі, коли він був створений, і до того, як він зберігався в базі даних (якщо тільки, не дай Бог, ви зберігаєте недійсні дані в БД !!!!). Так само не повинно бути обчислення значень, оскільки вони були вже обчислені до зберігання об'єкта. Об'єкт повинен виглядати так само, як це було зроблено до його збереження. Насправді, додаючи в геттери / сетери додаткові речі, ви фактично збільшуєте ризик того, що ви відтворите щось, що не є точною копією оригіналу.

Звичайно, ця функціональність була додана не просто так. Можливо, є кілька дійсних випадків використання для збереження доступу, однак вони, як правило, є рідкісними. Прикладом може бути те, що ви хочете уникнути збереження обчисленої величини, хоча ви можете задати питання, чому ви не обчислюєте його на вимогу в геттері значення або ліниво ініціалізуєте його в геттері. Особисто я не можу придумати жодного корисного випадку, і жодна з відповідей тут не дає відповіді на тему «Програмне забезпечення інженерії».


9
Відповідь інженерії програмного забезпечення: використання аксесуарів порушує DRY.
sourcedelica

1
@Martin У мене є запитання щодо останнього пункту вашої відповіді. Ви написали "Прикладом може бути те, що ви хочете уникнути збереження обчисленого значення". Як можна уникнути збереження обчисленої вартості, маючи доступ на основі властивості? Я знаю, що ви сперечаєтесь не робити цього, але я не розумію цього. Чи можете ви поясніть, будь ласка?
Geek,

4
@Geek Тепер, коли я прочитав це, я не зовсім впевнений. Минуло два роки, як я написав цю відповідь. Думаю, кращим прикладом може бути те, коли ви працюєте зі застарілою базою даних, і дані подаються по-різному до вашої об'єктної моделі - доступні пристрої можуть надати відображення між ними.
Мартін

23
Хороший випадок використання аксесуарів для картографування - це коли вам потрібно додати інформацію про карти до підкласів класів сторонніх організацій, які не пов'язані з будь-якою постійною реалізацією. Оскільки поля в цих класах приватні, вам доведеться переосмислювати аксесуари та додавати до них анотації на відображення. Іншим варіантом буде використання XML-картографування, але деякі речі зробити там дуже важко. Тож, якщо ви хочете отримати анотації та зіставити сторонні класи, підкласифікація їх та додавання приміток до аксесуарів - це шлях.
Елнур Абдурахімов

5
@ElnurAbdurrakhimov там ми ідемо, відмінний приклад. Дякую.
Мартін

79

Я вважаю за краще доступ до поля, тому що я не змушений надавати геттер / сетер для кожної власності.

Швидке опитування через Google свідчить про те, що більшість доступ є на місцях (наприклад, http://java.dzone.com/tips/12-feb-jpa-20-why-accesstype ).

Я вважаю, що доступ до поля - це ідіома, яку рекомендує Spring, але я не можу знайти посилання на це.

Є пов’язане питання ПУ, яке намагалося виміряти продуктивність і дійшло висновку, що "різниці немає".


якщо ви не надаєте сеттер getter в сутності, то яке використання цього поля ... ви не можете використовувати його будь-де в додатку, becuase поля є приватними
anshulkatta

1
Не пропонуємо геттерам і сетерам для ваших полів погану практику ?, я думаю, мій коментар тут не завжди правильний, оскільки я припускав публічне поле, хоча, очевидно, це може бути приватне поле, до якого ніколи не можна отримати доступ.
Mathijs Segers

3
@anshulkatta Я вважаю, що мені справді слід вирішити ваші запитання, тому що це все про інкапсуляцію. В ідеалі всі ваші поля повинні бути приватними, і, якщо можливо, у них не повинно бути ні геттерів, ні сетерів - це найкращий рівень інкапсуляції, на який ви можете сподіватися. Розгляньте перевірку паролів. 2 приватні поля passwordHash і failAttempts. Обидва можуть бути приватними, без геттера чи сетера. Вони використовуються bool checkPassword (строковий пароль), який хешує, перевіряє пароль PasswordHash, а потім оновлює невдалі спроби та повертає результат. Немає іншого коду для доступу до цих двох полів.
Мартін

2
@anshulkatta слід зазначити, що в OOP, getters і setters є анти-шаблоном, вони виходять з процедурного програмування, наявність класу з ними порушує принцип інкапсуляції і генерує багато кодового коду, тобто такого ж типу код повторюється знову і знову. Об'єкти повинні бути незмінними, якщо потрібна модифікація його властивостей, це слід робити методом, який робить щось більше, ніж просто повернення значення властивості.
Уріель Арвізу

Не так. "Антидіаграма" в даному випадку - це питання думки, а не догма. Зважаючи на це, доступ до поля все ще є кращим. Краща ідея - взагалі ухилятися від ORM-рішень. Дізнайтеся, як правильно писати SQL.
duffymo

38

Ось така ситуація, коли ВИ ХОТЛИ використовувати доступ до майнових аксесуарів. Уявіть, що у вас є загальний абстрактний клас із великою кількістю можливостей для успадкування у 8 конкретних підкласів:

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
 }

Тепер, як саме слід коментувати цей клас? Відповідь НЕ МОЖЕТЕ анотувати це взагалі за допомогою поля чи доступу до власності, тому що ви не можете вказати цільову сутність у цій точці. ВАМ МОЖЕТЕ анотувати конкретні реалізації. Але оскільки збережені властивості задекларовані в цьому суперкласі, ОБОВ'ЯЗКОВО використовувати доступ до властивостей у підкласах.

Доступ до поля - це не варіант у додатку з абстрактними загальними суперкласами.


2
дотик. Я не думав про це. Б'юсь об заклад, що сплячий режим виводить з цього шаленого sql.
Йосип Похоть

8
Ця проблема звучить механічно важко для вирішення без анотаційних властивостей, але я ніколи не стикався з випадком, коли мені потрібен був абстрактний родовий клас з великою кількістю реалізацій, який я також хотів зберегти. Як правило, я створюю ієрархію класів, щоб зробити мій об'єкт поліморфним (що робить його загальним родом розривів), а не лише для повторного використання коду. І "багато та багато впровадження" часто так чи інакше порушує SRP, і в такому випадку я б, мабуть, перемістив його в окремі класи. Чи є конкретний приклад, який робить цей випадок використання більш очевидним?
Мерлін Морган-Грехем

Єдиний конкретний приклад - це моя програма, яку я не можу описати в коментарі до 500 символів ;-)
HDave

3
Ви можете використовувати abstract T getOneThing(), і abstract void setOneThing(T thing), і використовувати доступ до полів.
Артуро Волпе

33

Я, як правило, віддаю перевагу та використовую аксесуари для власності:

  • Я можу додати логіку, якщо виникає потреба (як зазначено у прийнятій відповіді).
  • це дозволяє мені дзвонити foo.getId() без ініціалізації проксі (важливо при використанні Hibernate, поки HHH-3718 не буде вирішено).

Недолік:

  • це робить код менш читабельним, у вас є, наприклад, перегляд цілого класу, щоб побачити, чи є @Transientтам.

але тоді, якщо ви використовуєте постачальника JPA, який не має "проксі", то у вас немає такої проблеми, як "ваш постачальник JPA нав'язує вам".
Ніл Стоктон

13

Це дійсно залежить від конкретного випадку - обидва варіанти доступні не просто так. IMO він зводиться до трьох випадків:

  1. setter має певну логіку, яку не слід виконувати під час завантаження екземпляра з бази даних; наприклад, деяка перевірка значень відбувається в сетері, однак дані, що надходять від db, повинні бути дійсними (інакше вони не потраплять туди (:); в цьому випадку доступ до поля є найбільш підходящим;
  2. setter має певну логіку, до якої завжди слід звертатися, навіть під час завантаження екземпляра з db; наприклад, властивість, яка ініціалізується, використовується для обчислення деякого обчисленого поля (наприклад, майно - грошова сума, обчислена властивість - загалом кілька грошових властивостей одного і того ж екземпляра); у цьому випадку потрібен доступ до власності.
  3. Жоден із перерахованих вище випадків - тоді обидва варіанти застосовні, просто залишайтеся послідовними (наприклад, якщо вибір поля в цій ситуації є вибором, тоді використовуйте його весь час у подібній ситуації).

Я новачок у сплячому режимі і борюся з тим же питанням. Я думаю, цей пост дає найбільш чітку відповідь. Дякую.
Сем Левін

12

Я настійно рекомендую доступ до поля, а НЕ анотації на getters (доступ до власності), якщо ви хочете зробити щось більше в сеттерах, ніж просто встановити значення (наприклад, шифрування чи обчислення).

Проблема з доступом до властивостей полягає в тому, що сетери також викликаються при завантаженні об'єкта. Це працювало для мене чудово протягом багатьох місяців, поки ми не хотіли ввести шифрування. У нашому випадку використання ми хотіли зашифрувати поле в сетері та розшифрувати його в геттері. Проблема з доступом до власності полягала в тому, що коли Hibernate завантажував об'єкт, він також закликав сеттера заповнити поле і, таким чином, знову зашифрував зашифроване значення. У цій публікації також згадується це: Java Hibernate: Різне поведінка функції набору властивостей залежно від того, хто її викликає

Це викликало у мене головний біль, поки я не згадав про різницю між полем доступу та доступом до власності. Тепер я перемістив усі свої примітки з доступу власності до доступу до поля, і це працює нормально.


Так - я виявив, що якщо ви користуєтесь доступом до власності, ви дійсно нічого не можете зробити у своєму сетері, крім встановленого значення поля.
HDave

2
+1 Тримайтеся подалі від геттерів / сетер. Я використовую projectlombok.org і тримаю їх прихованими від розробників.
бхантол

11

Я вважаю за краще використовувати доступ із поля з наступних причин:

  1. Доступ до властивості може привести до дуже неприємних помилок при реалізації Equals / хеша - коді і посилань на поля безпосередньо (в протилежності через їх годувальник). Це пов’язано з тим, що проксі-сервер ініціалізується лише тоді, коли доступ до гетерів доступний, а доступ з прямого поля просто повернеться в нулевий.

  2. Доступ до властивості вимагає анотувати всі допоміжні методи (наприклад , AddChild / RemoveChild) як @Transient.

  3. За допомогою доступу до поля ми можемо приховати поле @Version, взагалі не виставляючи геттера. Геттер також може призвести до додавання сеттера, і versionполе ніколи не слід встановлювати вручну (що може призвести до дуже неприємних проблем). Усі збільшення версій повинні бути запущені через явне блокування OPTIMISTIC_FORCE_INCREMENT або PESSIMISTIC_FORCE_INCREMENT .


1. Як стратегія доступу на місцях перешкоджає цьому? Здається, це загальна проблема з проксі-серверами, незалежно від стилю доступу. 2. Ви впевнені, чи повинні це бути лише комунальні служби? (але гарний аргумент все одно). 3. Викриття аксесуарів для versionполя часто корисно в ситуаціях, коли замість відокремлених об'єктів використовуються DTO.
Драган Бозанович

1. Через час проксі ініціалізації проксі. 2. 100% впевнений. 3. Це дійсний пункт.
Влад Міхалча

Вибачте моє незнання та можливу відсутність тлумачення тексту (я не є носієм англійської мови). Просто для уточнення, доступ до поля - це тоді, коли потрібні не потрібні способи отримання / встановлення, тож для POJO, що використовується цілісно, ​​поля є загальнодоступними? Але ви говорите щось у першій темі, а пов’язана публікація блогу говорить про протилежне. Що я зрозумів, це те, що ви не можете використовувати рівних під час використання проксі-сервісів та доступу до поля.
MaikoID

Ні. Доступ до поля означає, що Hibernate використовує поля за допомогою відображень для читання атрибутів сутності. Щоб отримати детальнішу інформацію, перегляньте розділ Тип доступу в Посібнику зі сну .
Влад Міхалча

7

Я думаю, що коментувати властивість краще, оскільки оновлення полів безпосередньо порушує інкапсуляцію, навіть коли це робить ваш ORM.

Ось чудовий приклад того, де це спалить вас: ви, мабуть, хочете, щоб ваші примітки щодо переходу на сплячку та збереження в одному місці (або поля, або властивості) хотіли. Якщо ви хочете перевірити ваші перевірки на хибернальний валідатор, які позначені на полі, ви не можете використовувати макет вашої сутності, щоб ізолювати ваш тест одиниці лише на валідатор. Ой.


2
Ось чому ви ставите валідатори-анотації на аксесуари та постійні анотації на полях
рибалка

6

Я вважаю, що доступ до власності та доступ до поля дещо відрізняється щодо лінивої ініціалізації.

Розглянемо наступні карти для 2 основних бобів:

<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>

І наступні одиничні тести:

@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();
}

Ви побачите тонку різницю в необхідних виборах:

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

Тобто, для виклику fb.getId()потрібно вибрати, тоді як pb.getId()ні.


Це кумедно! :) Але я впевнений, що це конкретна поведінка. Я
Володимир Дюжев

Так, я думаю, це пов'язано з тим, що інструменти мають лише стійкі класи. Однак це дуже просто, оскільки поле id часто є тим полем, яке не має ділової цінності і не потребує жодного доступу.
Моріс Перрі

6

Дозвольте спробувати узагальнити найважливіші причини вибору доступу на місцях. Якщо ви хочете зануритися глибше, будь ласка, прочитайте цю статтю на моєму блозі: Стратегії доступу в JPA та Зимова сплячка - Що краще, доступ у поле чи власність?

Польовий доступ - це набагато кращий варіант. Ось 5 причин для цього:

Причина 1: Краща читаність вашого коду

Якщо ви використовуєте доступ на місцях, ви коментуєте атрибути вашої сутності за допомогою анотацій на карті. Розміщуючи визначення всіх атрибутів сутності у верхній частині свого класу, ви отримуєте відносно компактне уявлення про всі атрибути та їх відображення.

Причина 2. Опустіть способи отримання або встановлення, які не повинні викликати вашою заявкою

Ще одна перевага польового доступу полягає в тому, що ваш постачальник завзятості, наприклад, Hibernate або EclipseLink, не використовує методів отримання та встановлення ваших атрибутів сутності. Це означає, що вам не потрібно надавати жоден метод, який не повинен використовуватися у вашому бізнес-коді. Найчастіше це стосується методів встановлення створених атрибутів первинного ключа або стовпців версій. Ваш постачальник завзятості керує значеннями цих атрибутів, і ви не повинні їх встановлювати програмно.

Причина 3: Гнучка реалізація методів геттера та сетера

Оскільки ваш постачальник завзятості не викликає способи отримання та встановлення, вони не змушені виконувати жодні зовнішні вимоги. Ви можете реалізувати ці методи будь-яким способом. Це дає змогу реалізувати специфічні для бізнесу правила перевірки, запустити додаткову логіку бізнесу або перетворити атрибут сутності в інший тип даних.

Наприклад, ви можете використовувати це, щоб обернути необов'язкове об'єднання або атрибут у Java Optional.

Причина 4: Не потрібно маркувати корисні методи як @Transient

Ще одна перевага стратегії доступу на місцях полягає в тому, що вам не потрібно коментувати свої корисні методи @Transient. Ця примітка повідомляє вашого постачальника наполегливості, що метод або атрибут не є частиною стійкого стану сутності. Оскільки завдяки доступу до польового типу стійкий стан визначається атрибутами вашої сутності, ваша реалізація JPA ігнорує всі методи вашої сутності.

Причина 5: Уникайте помилок під час роботи з проксі

Hibernate використовує проксі для ліниво пов'язаних один до одного асоціацій, щоб він міг контролювати ініціалізацію цих асоціацій. Такий підхід працює чудово майже у всіх ситуаціях. Але це створює небезпечну проблему, якщо ви користуєтесь доступом на основі власності.

Якщо ви використовуєте доступ на основі властивостей, Hibernate ініціалізує атрибути проксі-об'єкта під час виклику методу getter. Це завжди так, якщо ви використовуєте об'єкт проксі у своєму коді бізнесу. Але досить багато рівних та хеш-код-реалізацій мають доступ до атрибутів безпосередньо. Якщо ви вперше отримуєте доступ до будь-якого з атрибутів проксі, ці атрибути залишаються неініціалізованими.


3

За замовчуванням постачальники JPA отримують доступ до значень полів сутності та відображають ці поля в стовпці бази даних, використовуючи доступ до власності JavaBean властивості (getter) та мутатор (setter). Таким чином, назви та типи приватних полів в об'єкті не мають значення для JPA. Натомість JPA розглядає лише імена та типи повернення аксесуарів властивостей JavaBean. Ви можете змінити це за допомогою @javax.persistence.Accessпримітки, яка дозволяє чітко вказати методологію доступу, яку повинен використовувати постачальник JPA.

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

Доступними параметрами для перерахунку AccessType є ВЛАСНІСТЬ (за замовчуванням) та FIELD. Завдяки ВЛАСНІСТЬ постачальник отримує та встановлює значення полів, використовуючи методи властивості JavaBean. FIELD змушує постачальника отримувати та встановлювати значення полів за допомогою полів примірника. Як найкраща практика, вам слід просто дотримуватися стандартних умов і використовувати властивості JavaBean, якщо у вас немає вагомих причин робити інше.

Ви можете розміщувати ці анотації про властивості на приватних полях або на публічних методах доступу. Якщо ви використовуєтеAccessType.PROPERTY (за замовчуванням) і анотуєте приватні поля замість аксесуарів JavaBean, імена полів повинні відповідати іменам властивостей JavaBean. Однак імена не повинні відповідати, якщо ви коментуєте аксесуари JavaBean. Так само, якщо ви використовуєте AccessType.FIELDта примічаєте аксесуари JavaBean замість полів, імена полів також повинні відповідати іменам властивостей JavaBean. У цьому випадку вони не повинні відповідати, якщо ви коментуєте поля. Найкраще просто бути послідовними та коментувати аксесуари JavaBean для AccessType.PROPERTYта поля для AccessType.FIELD .

Важливо, щоб ви ніколи не змішували анотації щодо властивостей JPA та анотації з поля JPA в одній суті. Це призводить до невказаної поведінки і, швидше за все, спричинить помилки.


2

Ми ще там?

Це давня презентація, але Род припускає, що анотація щодо доступу до власності заохочує анемічні моделі доменів і не повинна бути "за замовчуванням" способом коментування.


2

Іншим моментом на користь доступу до поля є те, що в іншому випадку ви змушені виставляти сетери для колекцій, а це, на мене, погана ідея, оскільки зміна стійкого екземпляра колекції на об'єкт, яким не керує Hibernate, безумовно порушить узгодженість ваших даних.

Тому я вважаю за краще колекції як захищені поля, ініціалізовані до порожніх реалізацій у конструкторі за замовчуванням, і виставляти лише їх гетерів. Тоді, тільки керовані операції , такі як clear(), remove(), і removeAll()т.д., можливо, ніколи не буде робити Hibernate не знають про зміни.


Ви не змушені нічого піддавати, оскільки сетери можуть бути захищені. Крім того, ці налаштування не є частиною інтерфейсу, що реалізується, тому навіть якщо вони були загальнодоступними, вони не є легко доступними.
HDave

2

Я віддаю перевагу полям, але я зіткнувся з однією ситуацією, яка, здається, змушує мене розміщувати анотації на учасниках.

З реалізацією Hibernate JPA, @Embeddedсхоже, не працює на полях. Так що це має продовжуватися на геттері. І як тільки ви це покладете на геттер, то різні @Columnпримітки також повинні надходити на них. (Я думаю, що сплячий не хоче тут змішувати поля та гетери.) А коли ви @Columnнадягаєте гетерів в одному класі, це, мабуть, має сенс робити це впродовж усього.


2

Я віддаю перевагу польовим аксесуарам. Код набагато чистіший. Усі примітки можна розмістити в одному розділі класу, і код читається набагато простіше.

Я знайшов ще одну проблему з доступом до властивостей: якщо у вашому класі є методи getXYZ, які НЕ відзначаються як асоційовані з стійкими властивостями, сплячий режим генерує sql для спроби отримати ці властивості, в результаті чого з’являються дуже заплутані повідомлення про помилки. Дві години витрачали даремно. Я не писав цього коду; Я завжди використовував польові аксесуари в минулому і ніколи не стикався з цим питанням.

Версії для сплячого режиму, які використовуються в цій програмі:

<!-- 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

Ви повинні вибрати доступ через поля над доступом через властивості. За допомогою полів ви можете обмежити надіслані та отримані дані. Завдяки властивостям via можна надіслати більше даних у якості хоста та встановити номінали G (які заводу встановлюють більшість властивостей загалом).




1

Ми створили об'єкти бобів та використали анотації для отримання «атрибутів» Проблема, з якою ми стикалися, полягає в наступному: деякі об'єкти мають складні правила щодо деяких властивостей щодо того, коли вони можуть бути оновлені. Рішення полягало в тому, щоб у кожному сеттеррі була деяка логіка бізнесу, яка визначала, чи змінюється фактичне значення чи ні, і якщо так, чи слід допускати зміну. Звичайно, Hibernate завжди може встановити властивості, тому ми закінчили дві групи сетерів. Досить потворно.

Читаючи попередні публікації, я також бачу, що посилання на властивості зсередини об'єкта може призвести до проблем із завантаженням колекцій.

Знизу я схиляюся до того, щоб коментувати поля в майбутньому.


0

Зазвичай боби є POJO, тому в будь-якому випадку вони мають приналежності.

Тож питання не в тому, "хто краще?", А просто "коли використовувати доступ до поля?". А відповідь - "коли вам не потрібен сетер / геттер для поля!".


4
Проблема полягає в тому, що ви не можете змішати доступ до поля та доступ до власності в POJO - вам доведеться вибрати один
Martin OConnor

Дійсно? Я, мабуть, забув це. У всякому разі, я завжди використовую POJO a d аксесуари.
Володимир Дюжев

Зауважте, що за допомогою JPA 2.0 (чого не було, коли запитання було задано) тепер ви можете змішувати типи доступу за допомогою анотації @AccessType.
mtpettyp

0

Я думаю про це, і я вибираю метод аксесуара

чому?

тому що акселератор поля та методу - це те саме, але якщо пізніше мені потрібна логіка в навантажувальному полі, я зберігаю переміщення всіх анотацій, розміщених у полях

з повагою

Грубхарт


0

Щоб зробити ваші заняття більш чистими, введіть анотацію в поле, а потім використовуйте @Access (AccessType.PROPERTY)


0

Обидва:

Специфікація EJB3 вимагає, щоб ви оголосили анотації про тип елемента, до якого будете отримувати доступ, тобто метод getter, якщо ви використовуєте доступ до властивостей, поле, якщо ви використовуєте поле доступу.

https://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/#entity-mapping


0

AccessType.PROPERTY: Реалізація стійкості EJB завантажує стан у ваш клас за допомогою методів "setter" JavaBean та виводить стан із класу за допомогою методів "getter" JavaBean. Це за замовчуванням.

AccessType.FIELD: стан завантажується та отримується безпосередньо з полів вашого класу. Не потрібно писати JavaBean "getters" та "setters".

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.