Зачем кому-то ставить аннотации на геттеры или сеттеры при использовании JPA для отображения классов? - PullRequest
36 голосов
/ 15 ноября 2010

Субъект все говорит ... Я не вижу никакого преимущества в том, чтобы люди объявляли аннотации на геттерах и / или установщиках.Для меня это имеет только один недостаток - распространение аннотаций по классу, что может сделать класс более нечитабельным.

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

Ответы [ 4 ]

42 голосов
/ 15 ноября 2010

Размещение аннотаций для методов заставляет JPA обращаться к свойствам через методы. Это имеет смысл, когда внутреннее состояние вашего объекта отличается от схемы базы данных:

@Entity
public class Employee {
    private String firstName;
    private String lastName;

    @Column(name = "EMP_NAME") // Due to legacy database schema
    public String getName() {
        return fisrtName + " " + lastName;
    }

    public void setName(String name) {
        ...
    }

    ... Getters and setters for firstName and lastName with @Transient ...
}

В JPA 2.0 вы можете указать тип доступа на детальном уровне с помощью @Access:

@Entity @Access(AccessType.FIELD)
public class Employee {
    @Access(AccessType.PROPERTY) @Column(name = "EMP_NAME")
    public String getName() { ... }
    ... other properties have field access ...
}
22 голосов
/ 16 ноября 2010

Зачем кому-то ставить аннотации на геттеры или сеттеры при использовании JPA для сопоставления классов?

Как уже упоминалось, использование доступа к свойству позволяет добавлять логику в геттер, есливозникает необходимость.

Но так как вопрос помечен , я упомяну еще одно ( огромное ) преимущество: доступ к свойству позволяет вам звонить foo.getId() без инициализации прокси .Вы не можете получить то же поведение при использовании доступа к полю.Эммануэль Бернард объясняет это ограничение доступа к полю следующим образом:

Это прискорбно, но ожидаемо.Это одно из ограничений доступа на уровне поля.По сути, мы не можем знать, что getId () действительно только идет и получает доступ к полю id.Поэтому нам нужно загрузить весь объект, чтобы быть в безопасности.

Так что да, использование доступа к свойствам затрудняет чтение кода, например, вам нужно просмотреть целый класс, чтобы увидеть, есть ли какие-либо @Transient там.Но для меня выгода (по крайней мере, с ) намного перевешивает этот недостаток.

Смежные вопросы

Ссылки

2 голосов
/ 03 июля 2014

Ответы даны правильно.Методы аннотирования вместо свойств дают вам:

  1. Право использовать getId (), если оно помечено как значение @Id, для получения значения внешнего ключа от прокси-объекта без фактической загрузкиэто из БД.

  2. Вы можете создавать методы получения / установки, которые обновляют состояние внутреннего объекта, которого нет в базе данных.Я использовал это при извлечении сжатого состояния из БД, которое я хочу распаковать внутри объекта в более пригодный для использования внутренний элемент данных.Сеттеры и геттеры устанавливают и получают сжатое состояние, а DB и Hibernate не «знают» о несжатом внутреннем элементе.

Есть один недостаток, который я затронул:

A.Ваши сеттеры должны быть довольно простыми.Hibernate ожидает, что они будут делать то, что было бы достигнуто путем прямого присвоения члену данных.Метод "setCategory", который не только устанавливает категорию, но и обновляет соответствующий объект Category для отображения взаимосвязи, может привести к неприятностям.

0 голосов
/ 22 сентября 2016

Я использую аннотации для методов получения / установки, потому что у меня есть API, отделенный от реализации, и я хотел оставить часть API полностью свободной от фреймворка, позволяя мне переключать каркасы или предоставлять различные реализации.Например, сейчас я использую spring-data-jpa, но с помощью API ниже я могу легко переключиться на spring-jdbc или любую другую платформу.

Что я сделал, так это определил интерфейсы для контроллера,хранилище и сущность, как таковая:

public interface MyEntityController<T extends MyEntity> {
    Iterable<T> listEntities();
    T getEntity(Long id);
}

public interface MyEntityService<T extends MyEntity> {
    Iterable<T> findAll();
    T findById(Long id);
}

public interface MyEntityRepository<T extends MyEntity> {
    Iterable<T> findAll();
    T findOne(Long id);
}

// no JPA annotations here
public abstract class MyEntity {
    protected Long id;
    protected String myField;
}

Далее я просто реализую MyEntity следующим образом и использую MyEntityImpl для реализаций контроллера, службы и хранилища:

@Entity
public class MyEntityImpl extends MyEntity {
    @Id public long getId() { return id; }
    @Column public String getMyField() { return myField };
    // setters, etc
}

@Repository
public interface MyEntityRepositoryImpl extends MyEntityRepository, JPARepository<MyEntityImpl, Long> {
}

У меня естьуже проверил и работает нормально.Простое аннотирование MyEntityImpl с помощью @Entity не сработало бы, поскольку суперкласс должен был бы быть @MappedSuperclass.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...