Hibernate Аннотации - Что лучше, доступ к полю или собственности? - PullRequest
124 голосов
/ 27 февраля 2009

Этот вопрос имеет некоторое отношение к Вопросу размещения аннотации в спящем режиме .

Но я хочу знать, что лучше ? Доступ через свойства или доступ через поля? Каковы преимущества и недостатки каждого?

Ответы [ 25 ]

2 голосов
/ 09 декабря 2010

Мы уже там

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

2 голосов
/ 17 декабря 2018

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

2 голосов
/ 11 июня 2013

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

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

2 голосов
/ 06 апреля 2017

По умолчанию поставщики 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. ПОЛЕ делает поставщик получает и устанавливает значения полей, используя поля экземпляра. Как лучшая практика, вы должны просто придерживаться по умолчанию и используйте свойства JavaBean, если у вас нет веских причин поступить иначе.

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

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

2 голосов
/ 01 июня 2014

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

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

2 голосов
/ 14 марта 2012

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

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

Hibernate версии, используемые в этом приложении:

<!-- 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>
1 голос
/ 17 декабря 2018

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1 голос
/ 27 апреля 2010

У меня был тот же вопрос относительно accesstype в спящем режиме, и я нашел некоторые ответы здесь .

1 голос
/ 16 июля 2012

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

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

Итог, я бы склонялся к аннотированию полей в будущем.

1 голос
/ 22 ноября 2010

Я решил ленивую инициализацию и доступ к полю здесь Hibernate один к одному: getId () без выборки всего объекта

...