Dlaczego ktoś powinien umieszczać adnotacje na geterach lub seterach, gdy używa JPA do mapowania klas?

Tester mówi wszystko... Nie widzę korzyści z tego, że ludzie deklarują adnotacje na geterach i / lub seterach. Dla mnie ma to tylko wadę rozprzestrzeniania adnotacji po klasie, co może sprawić, że klasa będzie bardziej nieczytelna.

Umieszczanie adnotacji na polach wyraźnie zmniejsza ilość kodu do wysłania, gdy potrzebujesz pomocy. To tylko mała zaleta. Ale umieszczanie adnotacji na metodach nie służyłoby mi nic.

Author: Kawu, 2010-11-15

4 answers

Umieszczenie adnotacji na metodach wymusza na JPA dostęp do właściwości za pomocą metod. Ma to sens, gdy wewnętrzny stan obiektu różni się od schematu bazy danych:

@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 ...
}

W JPA 2.0 możesz określić typ dostępu na poziomie drobnoziarnistym za pomocą @Access:

@Entity @Access(AccessType.FIELD)
public class Employee {
    @Access(AccessType.PROPERTY) @Column(name = "EMP_NAME")
    public String getName() { ... }
    ... other properties have field access ...
}
 41
Author: axtavt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-15 20:21:26

Dlaczego ktoś powinien umieszczać adnotacje na geterach lub seterach, gdy używa JPA do mapowania klas?

Jak już wspomniano, użycie właściwości access pozwala dodać logikę w getterze, jeśli zajdzie taka potrzeba.

Ale skoro pytanie jest oznaczone hibernate , wspomnę jeszcze o innym (huge) benefit: property access pozwala na wywołanie foo.getId() bez inicjowania proxy. Nie można uzyskać takiego samego zachowania podczas korzystania z dostępu do pola. Emmanuel Bernard wyjaśnia to ograniczenie dostępu do pola w następujący sposób:

To niefortunne, ale oczekiwane. To jedno z ograniczeń dostępu na poziomie pola. Zasadniczo nie mamy sposobu, aby wiedzieć, że getId() rzeczywiście tylko przejść i uzyskać dostęp do pola id. Więc musimy załadować cały obiekt, aby być bezpiecznym.

Więc tak, korzystanie z dostępu do właściwości utrudnia odczyt kodu, musisz na przykład przejrzeć całą klasę, aby sprawdzić, czy w pobliżu są jakieś @Transient. Ale dla mnie, korzyść (przynajmniej z hibernate) zdecydowanie przewyższa tę wadę.

Podobne pytania

Referencje

 22
Author: Pascal Thivent,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:06

Podane odpowiedzi są poprawne. Adnotacja metod zamiast właściwości daje:

  1. Prawo do użycia getId (), jeśli jest oznaczona jako wartość @ Id, aby uzyskać wartość klucza obcego z obiektu proxy bez ładowania go z DB.

  2. Można tworzyć gettery / settery, które aktualizują wewnętrzny stan obiektu, który nie znajduje się w bazie danych. Użyłem tego podczas pobierania skompresowanego stanu z DB, który chcę zdekompresować wewnątrz obiektu do bardziej użytecznego wewnętrzne dane członków. Setters i getters ustawiają i pobierają stan skompresowany, a DB i Hibernate nie "wiedzą" o nieskompresowanym członie wewnętrznym.

Jest jedna wada, którą trafiłem:

A. Twoje setery muszą być dość proste. Hibernate oczekuje, że zrobi to, co zostanie osiągnięte przez bezpośrednie przypisanie do punktu odniesienia członka. Metoda "setCategory", która nie tylko ustawia kategorię, ale także aktualizuje odpowiedni obiekt kategorii, aby pokazać związek, może uzyskać masz kłopoty.

 2
Author: Clint,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-02 23:13:00

Używam adnotacji w getters / setters, ponieważ mam API oddzielone od implementacji i chciałem, aby część API była całkowicie wolna od frameworków, umożliwiając mi przełączanie frameworków lub dostarczanie różnych implementacji. Na przykład, w tej chwili używam spring-data-jpa, ale z poniższym API mogę łatwo przełączyć się na spring-jdbc lub inny framework.

To, co zrobiłem, to zdefiniowanie interfejsów dla kontrolera, repozytorium i encji, jako takie:

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

Następnie implementuję MyEntity w następujący sposób i używam MyEntityImpl dla implementacji kontrolera, usługi i repozytorium:

@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> {
}

Już go przetestowałem i działa dobrze. Samo przypisanie MyEntityImpl z @Entity nie zadziałałoby, ponieważ Klasa nadrzędna musiałaby być @MappedSuperclass.

 0
Author: Tarek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-22 14:27:20