Hibernate Аннотации - что лучше, доступ к полю или собственности?

Ответы:

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 или другую библиотеку для сопоставления / клонирования bean на основе свойств получателя / установщика), вы получите гарантию, что библиотека синхронизирована с постоянством manager (оба используют геттер / сеттер).

Мигель Пинг
источник
17
Обратите внимание, что это касается того, как ORM получает доступ к вашим полям / свойствам, а не к коду вашего приложения. С доступом к полю ваш метод getNickName () будет работать именно так, как вы ожидаете. То же самое неверно, если вы используете постоянные «свойства» вне геттеров / сеттеров. Именно здесь вы можете столкнуться с проблемами с доступом к свойству и отложенной загрузкой. Так что нет, я в целом не согласен с этим аргументом. Однако в последний раз, когда я проверял, у Hibernate были проблемы с доступом к полям @Id.
Роб Бигрейв
11
этот ответ не имеет отношения к вопросу. Лучший ответ от duffymo
Janning
10
внутри методов доступа не должно быть никакой бизнес-логики. это не очевидное поведение.
iuriisusuk
Почему этот ответ отмечен как правильный? Неверно, что вы можете сопоставить поле и таким же образом предоставить ему сеттер / получатель.
Удача
247

Есть аргументы в пользу того и другого, но большинство из них проистекает из определенных требований пользователя: «что, если вам нужно добавить логику для», или «xxxx нарушает инкапсуляцию». Однако никто не прокомментировал эту теорию и не привел должным образом аргументированных аргументов.

Что на самом деле делает Hibernate / JPA, когда он сохраняет объект - ну, он сохраняет СОСТОЯНИЕ объекта. Это означает, что хранить его так, чтобы его можно было легко воспроизвести.

Что такое инкапсуляция? Инкапсуляция означает инкапсуляцию данных (или состояния) с помощью интерфейса, который приложение / клиент может использовать для безопасного доступа к данным - поддерживая их согласованность и действительность.

Думайте об этом как MS Word. MS Word хранит в памяти модель документа - документы СОСТОЯНИЕ. Он представляет собой интерфейс, который пользователь может использовать для изменения документа - набор кнопок, инструментов, команд клавиатуры и т. Д. Однако, когда вы решите сохранить (сохранить) этот документ, он сохраняет внутреннее состояние, а не набор нажатий клавиш и щелчки мыши, используемые для его генерации.

Сохранение внутреннего состояния объекта НЕ нарушает инкапсуляцию - иначе вы не совсем понимаете, что такое инкапсуляция и почему она существует. На самом деле это похоже на сериализацию объектов.

По этой причине в НАИБОЛЕЕ СЛУЧАЯХ уместно сохранять ПОЛЯ, а не АКСЕССУАРЫ. Это означает, что объект можно точно воссоздать из базы данных в том виде, в котором он был сохранен. Он не должен нуждаться в какой-либо проверке, потому что это было сделано на оригинале, когда он был создан, и до того, как он был сохранен в базе данных (если, не дай бог, вы храните неверные данные в БД !!!!). Точно так же не должно быть необходимости вычислять значения, поскольку они уже были рассчитаны до того, как объект был сохранен. Объект должен выглядеть так же, как и до сохранения. Фактически, добавляя дополнительный материал в методы получения / установки, вы фактически увеличиваете риск того, что вы воссоздаете что-то, что не является точной копией оригинала.

Конечно, эта функциональность была добавлена ​​неспроста. Могут быть некоторые допустимые варианты использования для сохранения средств доступа, однако, как правило, они будут редкими. Примером может быть то, что вы хотите избежать сохранения вычисленного значения, хотя вы можете задать вопрос, почему вы не вычисляете его по запросу в получателе значения или лениво инициализируете его в получателе. Лично я не могу придумать ни одного хорошего варианта использования, и ни один из ответов здесь не дает ответа на вопрос «Разработка программного обеспечения».

Мартин
источник
9
Ответ разработки программного обеспечения: использование методов доступа нарушает СУХОЙ.
sourcedelica
1
@Martin У меня есть дополнительный вопрос по последнему абзацу вашего ответа. Вы написали: «Примером может быть то, что вы не хотите сохранять вычисленное значение». Как избежать сохранения вычисленного значения, имея доступ на основе свойств? Я знаю, что вы возражаете против этого, но я не понимаю сути дела. Можете ли вы объяснить, пожалуйста?
Компьютерщик
4
@Geek Теперь, когда я перечитал это, я сам не совсем уверен. Прошло два года с тех пор, как я написал этот ответ. Я думаю, что лучшим примером может быть ситуация, когда вы работаете с устаревшей базой данных, и данные представляются иначе, чем ваша объектная модель - аксессоры могут обеспечить сопоставление между ними.
Мартин
23
Хороший вариант использования средств доступа для сопоставления - это когда вам нужно добавить информацию о сопоставлении в подклассы сторонних классов сущностей, которые не привязаны к какой-либо реализации сохраняемости. Поскольку в этих классах поля являются закрытыми, вам необходимо переопределить методы доступа и добавить к ним аннотации сопоставления. Другой вариант - использовать отображение XML, но некоторые вещи здесь сделать очень сложно. Итак, если вам нужны аннотации и сопоставление сторонних классов, их создание подклассов и добавление аннотаций к средствам доступа - лучший способ.
Эльнур Абдуррахимов
5
@ElnurAbdurrakhimov, вот и отличный пример. Спасибо.
Мартин
80

Я предпочитаю доступ к полю, потому что таким образом я не обязан предоставлять getter / setter для каждого свойства.

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

Я полагаю, что полевой доступ - это идиома, рекомендованная Spring, но я не могу найти ссылку, подтверждающую это.

Есть связанный вопрос SO, который пытался измерить производительность и пришел к выводу, что «нет разницы».

duffymo
источник
если вы не предоставляете установщик getter в сущности, тогда как использовать это поле ... вы не можете использовать его нигде в приложении, потому что поля являются частными
anshulkatta
1
Разве не предоставляет метод получения и установки для ваших полей плохую практику? Я полагаю, что мой комментарий здесь не всегда верен, поскольку я предполагал открытое поле, хотя оно, очевидно, могло быть частным полем, к которому никогда не осуществляется доступ.
Mathijs Segers
3
@anshulkatta Я чувствую, что действительно должен ответить на ваши вопросы, поскольку именно в этом заключается суть инкапсуляции. В идеале все ваши поля должны быть закрытыми и, если возможно, у них не должно быть геттеров или сеттеров - это лучший уровень инкапсуляции, на который вы можете надеяться. Рассмотрим программу проверки паролей. 2 приватных поля passwordHash и failedAttempts. Оба могут быть частными без получения или установки. Они используются bool checkPassword (строковый пароль), который хеширует, проверяет на соответствие passwordHash, а затем обновляет failedAttempts и возвращает результат. Нет необходимости в другом коде для доступа к этим двум полям.
Мартин
2
@anshulkatta следует отметить, что в ООП геттеры и сеттеры являются анти-шаблоном, они происходят из процедурного программирования, наличие класса с ними нарушает принцип инкапсуляции и генерирует много шаблонного кода, то есть того же типа код повторяется снова и снова. Объекты должны быть неизменяемыми, если требуется модификация их свойств, это должно выполняться с помощью метода, который делает нечто большее, чем просто возвращает значение свойства.
Уриэль Арвизу
Не так. «Антипаттерн» в данном случае - вопрос мнения, а не догмы. С учетом сказанного, доступ к полю все еще предпочтительнее Лучше всего вообще отказаться от решений ORM. Научитесь писать правильный SQL.
duffymo
38

Вот ситуация, когда вам НЕОБХОДИМО использовать средства доступа к свойствам. Представьте, что у вас есть абстрактный класс GENERIC с большим количеством реализаций для наследования в 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
 }

Как именно аннотировать этот класс? Ответ: ВЫ НЕ МОЖЕТЕ аннотировать его с помощью доступа к полю или свойству, потому что вы не можете указать целевую сущность на этом этапе. Вы ДОЛЖНЫ аннотировать конкретные реализации. Но поскольку постоянные свойства объявлены в этом суперклассе, вы ДОЛЖНЫ использовать доступ к свойствам в подклассах.

Доступ к полям невозможен в приложении с абстрактными универсальными суперклассами.

HDave
источник
2
Touche. Я не думал об этом. Бьюсь об заклад, Hibernate предлагает какой-то сумасшедший sql для них.
Джозеф Ласт
8
Эта проблема кажется механически сложной для решения без аннотирования свойств, но я никогда не сталкивался со случаем, когда мне требовался абстрактный обобщенный класс с большой реализацией, который я также хотел сохранить. Обычно я создаю иерархию классов, чтобы сделать мой объект полиморфным (что делает его универсальным видом разрывов), а не только для повторного использования кода. И «множество и много реализаций» часто так или иначе нарушают SRP, и в этом случае я бы, вероятно, переместил бы его в отдельные классы. Есть ли конкретный пример, который делает этот вариант использования более очевидным?
Мерлин Морган-Грэм
Единственный конкретный пример, который у меня есть, - это мое приложение, которое я не могу описать в 500-символьном комментарии ;-)
HDave
3
Вы можете использовать abstract T getOneThing(), и abstract void setOneThing(T thing), и использовать доступ к полю.
Артуро Вольпе
33

Я склонен предпочесть и использовать средства доступа к собственности:

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

недостаток:

  • это делает код менее читаемым, например, вам нужно просмотреть весь класс, чтобы увидеть, есть ли там @Transientгде-то.
Паскаль Тивент
источник
но если вы используете провайдера JPA, у которого нет «прокси», то у вас не будет этой проблемы, известной как «ваш провайдер JPA навязывает вам».
Нил Стоктон
13

Это действительно зависит от конкретного случая - оба варианта доступны не зря. ИМО это сводится к трем случаям:

  1. У установщика есть некоторая логика, которая не должна выполняться во время загрузки экземпляра из базы данных; например, некоторая проверка значения происходит в установщике, однако данные, поступающие из db, должны быть действительными (иначе они не попали бы туда (:); в этом случае доступ к полю является наиболее подходящим;
  2. У setter есть некоторая логика, которую нужно вызывать всегда, даже во время загрузки экземпляра из db; например, инициализируемое свойство используется при вычислении некоторого вычисляемого поля (например, свойство - денежная сумма, вычисляемое свойство - всего нескольких денежных свойств одного и того же экземпляра); в этом случае требуется доступ к собственности.
  3. Ни один из вышеперечисленных случаев - тогда применимы оба варианта, просто оставайтесь последовательными (например, если в этой ситуации предпочтительным вариантом является доступ к полю, используйте его все время в аналогичной ситуации).
01es
источник
Я новичок в Hibernate и борюсь с тем же вопросом. Я думаю, что этот пост дает наиболее четкий ответ. Спасибо.
Сэм Левин
12

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

Проблема с доступом к свойствам заключается в том, что установщики также вызываются при загрузке объекта. У меня это работало много месяцев, пока мы не захотели ввести шифрование. В нашем случае мы хотели зашифровать поле в установщике и расшифровать его в получателе. Теперь проблема с доступом к свойствам заключалась в том, что, когда Hibernate загружал объект, он также вызывал сеттер для заполнения поля и, таким образом, снова зашифровывал зашифрованное значение. В этом сообщении также упоминается следующее: Java Hibernate: различное поведение функции набора свойств в зависимости от того, кто ее вызывает.

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

Christoph
источник
Да, я обнаружил, что если вы используете доступ к свойствам, вы действительно не можете ничего делать в своем сеттере, кроме установки значения поля.
HDave 01
2
+1 Держитесь подальше от геттеров / сеттеров. Я использую projectlombok.org и скрываю их от разработчиков.
bhantol 02
11

Я предпочитаю использовать доступ к полю по следующим причинам:

  1. Доступ к свойству может привести к очень неприятным ошибкам при реализации Equals / хэша - коде и ссылок на поля непосредственно (в противоположности через их добытчик). Это связано с тем, что прокси-сервер инициализируется только при доступе к геттерам, а прямой доступ к полю просто вернет null.

  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 использует поля через отражения для чтения атрибутов сущности. Дополнительные сведения см. В разделе «Тип доступа» в Руководстве пользователя Hibernate .
Влад Михалча,
7

Я думаю, что аннотирование свойства лучше, потому что обновление полей напрямую нарушает инкапсуляцию, даже когда ваш ORM делает это.

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

Джастин Стандарт
источник
2
Вот почему вы помещаете аннотации-валидаторы для средств доступа и аннотации-персистентности в поля
Fishbone
6

Я полагаю, что доступ к свойству и доступ к полю немного отличаются в отношении отложенной инициализации.

Рассмотрим следующие сопоставления для двух основных bean-компонентов:

<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()этого - нет.

Инструментарий
источник
Это смешно! :) Но я уверен, что это зависит от конкретной реализации. I
Владимир Дюжев
Да, я думаю, это связано с тем, что инструментированы только постоянные классы. Однако это жалко, потому что поле id часто является единственным полем, которое не имеет никакого значения для бизнеса и не требует никаких средств доступа.
Морис Перри,
6

Позвольте мне попытаться обобщить наиболее важные причины выбора полевого доступа. Если вы хотите погрузиться глубже, прочтите эту статью в моем блоге: Стратегии доступа в JPA и Hibernate - что лучше, доступ к полю или к свойству?

Полевой доступ - безусловно, лучший вариант. Вот 5 причин для этого:

Причина 1: лучшая читаемость вашего кода

Если вы используете доступ на основе полей, вы аннотируете свои атрибуты объекта с помощью аннотаций сопоставления. Поместив определение всех атрибутов сущности в начало вашего класса, вы получите относительно компактное представление всех атрибутов и их сопоставлений.

Причина 2: пропустите методы получения или установки, которые не должны вызываться вашим приложением

Еще одно преимущество доступа на основе полей заключается в том, что ваш поставщик постоянства, например Hibernate или EclipseLink, не использует методы получения и установки атрибутов вашей сущности. Это означает, что вам не нужно предоставлять какой-либо метод, который не должен использоваться вашим бизнес-кодом. Чаще всего это касается методов установки сгенерированных атрибутов первичного ключа или столбцов версии. Ваш поставщик сохраняемости управляет значениями этих атрибутов, и вам не следует устанавливать их программно.

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

Поскольку ваш поставщик сохраняемости не вызывает методы получения и установки, они не обязаны выполнять какие-либо внешние требования. Вы можете реализовать эти методы любым удобным для вас способом. Это позволяет реализовать бизнес-правила проверки, запускать дополнительную бизнес-логику или преобразовывать атрибут сущности в другой тип данных.

Вы можете, например, использовать это, чтобы обернуть необязательную ассоциацию или атрибут в Java Optional.

Причина 4: нет необходимости отмечать служебные методы как @Transient

Еще одно преимущество стратегии доступа на основе полей состоит в том, что вам не нужно аннотировать свои служебные методы с помощью @Transient. Эта аннотация сообщает вашему провайдеру постоянства, что метод или атрибут не является частью постоянного состояния сущности. И поскольку при доступе к типу поля постоянное состояние определяется атрибутами вашей сущности, ваша реализация JPA игнорирует все методы вашей сущности.

Причина 5: Избегайте ошибок при работе с прокси

Hibernate использует прокси для ленивых однозначных ассоциаций чтобы контролировать инициализацию этих ассоциаций. Такой подход отлично работает почти во всех ситуациях. Но это создает опасную ловушку, если вы используете доступ на основе свойств.

Если вы используете доступ на основе свойств, Hibernate инициализирует атрибуты прокси-объекта при вызове метода получения. Это всегда так, если вы используете прокси-объект в своем бизнес-коде. Но довольно много реализаций equals и hashCode обращаются к атрибутам напрямую. Если вы обращаетесь к любому из атрибутов прокси впервые, эти атрибуты все еще не инициализированы.

Торбен Янссен
источник
3

По умолчанию провайдеры JPA получают доступ к значениям полей сущностей и сопоставляют эти поля со столбцами базы данных, используя методы доступа к свойствам JavaBean (getter) и мутатора (setter) объекта. Таким образом, имена и типы личных полей в сущности не имеют значения для JPA. Вместо этого JPA просматривает только имена и возвращаемые типы средств доступа к свойствам JavaBean. Вы можете изменить это с помощью @javax.persistence.Accessаннотации, которая позволяет вам явно указать методологию доступа, которую должен использовать поставщик JPA.

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

Для перечисления AccessType доступны следующие параметры: PROPERTY (по умолчанию) и FIELD. С PROPERTY провайдер получает и устанавливает значения полей с помощью методов свойств JavaBean. FIELD позволяет поставщику получать и устанавливать значения полей с помощью полей экземпляра. Лучше всего придерживаться значений по умолчанию и использовать свойства JavaBean, если у вас нет веских причин поступить иначе.

Вы можете поместить эти аннотации свойств либо в частные поля, либо в общедоступные методы доступа. Если вы используете AccessType.PROPERTY(по умолчанию) и аннотируете частные поля вместо методов доступа JavaBean, имена полей должны соответствовать именам свойств JavaBean. Однако имена не обязательно должны совпадать, если вы аннотируете методы доступа JavaBean. Аналогичным образом, если вы используете AccessType.FIELDи аннотируете методы доступа JavaBean вместо полей, имена полей также должны соответствовать именам свойств JavaBean. В этом случае они не должны совпадать, если вы аннотируете поля. Лучше всего быть последовательным и аннотировать методы доступа JavaBean для AccessType.PROPERTYи поля для AccessType.FIELD.

Важно, чтобы вы никогда не смешивали аннотации свойств JPA и аннотации полей JPA в одной и той же сущности. Это приведет к неопределенному поведению и, скорее всего, приведет к ошибкам.

Faraz
источник
2

Мы уже на месте

Это старая презентация, но Род предполагает, что аннотации при доступе к собственности поощряют анемичные модели предметной области и не должны быть способом аннотирования «по умолчанию».

Мануэль Паласио
источник
2

Еще один аргумент в пользу доступа к полям заключается в том, что в противном случае вы также будете вынуждены открывать сеттеры для коллекций, что, на мой взгляд, является плохой идеей, так как изменение экземпляра постоянной коллекции на объект, не управляемый Hibernate, определенно нарушит согласованность ваших данных.

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

Иржи Выпедржик
источник
Вы не обязаны подвергать себя опасности, поскольку сеттеры могут быть защищены. Кроме того, эти сеттеры не являются частью реализуемого интерфейса, поэтому, даже если они были общедоступными, они не были легко доступны.
HDave 01
2

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

С реализацией Hibernate JPA, @Embeddedпохоже, не работает с полями. Так что это должно идти на добытчик. И как только вы поместите это в получатель, тогда различные @Columnпримечания также должны появиться и в получателе. (Я думаю, Hibernate не хочет смешивать здесь поля и геттеры.) И если вы добавляете @Columnгеттеры в один класс, вероятно, имеет смысл делать это повсюду.


источник
2

Я предпочитаю полевые средства доступа. Код намного чище. Все аннотации могут быть размещены в одном разделе класса, и код намного легче читать.

Я обнаружил еще одну проблему со средствами доступа к свойствам: если у вас есть методы getXYZ в вашем классе, которые НЕ аннотированы как связанные с постоянными свойствами, hibernate генерирует 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

Вы должны выбрать доступ через поля вместо доступа через свойства. С помощью полей вы можете ограничить отправленные и полученные данные. С помощью свойств через, вы можете отправить больше данных в качестве хоста, и установить G деноминации (какой завод в целом установил большинство свойств).

user10801787
источник
1

Мы создали бины сущностей и использовали аннотации геттеров. Проблема, с которой мы столкнулись, заключается в следующем: у некоторых сущностей есть сложные правила для некоторых свойств, касающихся того, когда они могут быть обновлены. Решение заключалось в том, чтобы иметь некоторую бизнес-логику в каждом установщике, которая определяет, изменилось ли фактическое значение и, если да, должно ли изменение быть разрешено. Конечно, Hibernate всегда может устанавливать свойства, поэтому мы получили две группы установщиков. Довольно уродливые.

Читая предыдущие сообщения, я также вижу, что ссылка на свойства изнутри сущности может привести к проблемам с загрузкой коллекций.

В итоге, я бы предпочел аннотировать поля в будущем.

Steve11235
источник
0

Обычно bean-компоненты являются POJO, поэтому у них в любом случае есть аксессоры.

Так что вопрос не в том, «что лучше?», А просто в том, «когда использовать доступ к полям?». И ответ - «когда вам не нужен сеттер / геттер для поля!».

Владимир Дюжев
источник
4
Проблема в том, что вы не можете смешивать доступ к полю и доступ к собственности в POJO - вам нужно выбрать одно
Мартин Оконнор,
В самом деле? Я, должно быть, забыл об этом. В любом случае, я всегда использую POJO и d аксессоры.
Владимир Дюжев
Обратите внимание, что в JPA 2.0 (которого не было, когда задавался этот вопрос) теперь вы можете смешивать типы доступа с помощью аннотации @AccessType.
mtpettyp
0

я думаю об этом и выбираю метод accesor

Зачем?

потому что поле и метод доступа совпадают, но если позже мне понадобится немного логики в поле загрузки, я сохраню все аннотации, помещенные в поля

С уважением

Grubhart

user261548
источник
0

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

Ely
источник
0

Обе :

Спецификация EJB3 требует, чтобы вы объявляли аннотации к типу элемента, к которому будет осуществляться доступ, то есть к методу получения, если вы используете доступ к свойствам, и к полю, если вы используете доступ к полю.

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

moueza
источник
0

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

AccessType.FIELD: состояние загружается и извлекается непосредственно из полей вашего класса. Вам не нужно писать "геттеры" и "сеттеры" JavaBean.

Дарья Ю
источник