Подтвердить что ты не робот

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

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

Помещение аннотаций на поля ясно уменьшает количество кода для отправки при необходимости помощи. Однако это крошечное преимущество. Но аннотации к методам не будут иметь для меня никакой цели.

4b9b3361

Ответ 1

Помещение аннотаций на методы заставляет 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 ...
}

Ответ 2

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

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

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

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

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

Связанные вопросы

Ссылки

Ответ 3

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

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

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

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

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

Ответ 4

Я использую аннотации на getters/setters, потому что у меня есть 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.