최대 절전 모드 주석-필드 또는 속성 액세스 중 어떤 것이 더 좋습니까?


답변:


33

필요할 때마다 접근 자에 비즈니스 로직을 추가 할 수 있기 때문에 접근자를 선호합니다. 예를 들면 다음과 같습니다.

@Entity
public class Person {

  @Column("nickName")
  public String getNickName(){
     if(this.name != null) return generateFunnyNick(this.name);
     else return "John Doe";
  }
}

또한 다른 JSON을 믹스에 던지면 (예 : JSON 변환 lib 또는 BeanMapper 또는 Dozer 또는 getter / setter 속성을 기반으로하는 다른 bean 매핑 / 복제 라이브러리와 같이) lib가 지속성과 동기화되어 있음을 보장합니다 관리자 (둘 다 getter / setter를 사용하십시오).


17
이것은 ORM이 응용 프로그램 코드가 아닌 필드 / 속성에 액세스하는 방법에 관한 것입니다. 필드 액세스를 사용하면 getNickName () 메소드가 예상대로 정확하게 작동합니다. getter / setter 외부에서 지속적 '속성'을 사용하는 경우에도 마찬가지입니다. 여기에서 자산 접근 및 지연 로딩 문제가 발생할 수 있습니다. 따라서, 나는이 주장에 일반적으로 동의하지 않습니다. 그러나 마지막으로 Hibernate를 확인했을 때 @Id 필드의 필드 액세스에 문제가있었습니다.
Rob Bygrave 1

11
이 답변은 질문과 관련이 없습니다. duffymo의 최고의 답변
Janning

9
접근 자 내부에는 비즈니스 로직이 없어야합니다. 그것은 명백한 행동이 아닙니다.
iuriisusuk

이 응답 마크가 왜 정확합니까? 필드를 매핑하고 동일한 방식으로 setter / getter를 제공 할 수 있다는 것은 사실이 아닙니다.
Lucke

246

두 가지 모두에 대한 논거가 있지만 대부분의 사용자 요구 사항은 "논리를 추가해야하는 경우"또는 "xxxx가 캡슐화를 중단합니다"라는 특정 사용자 요구 사항에서 비롯됩니다. 그러나 아무도 이론에 대해 실제로 의견을 말하지 않았으며 합리적으로 합리적인 주장을 제시했습니다.

Hibernate / JPA는 객체를 유지할 때 실제로하는 일-객체의 상태를 유지합니다. 즉, 쉽게 재현 할 수있는 방식으로 보관해야합니다.

캡슐화 란 무엇입니까? 캡슐화는 응용 프로그램 / 클라이언트가 데이터에 안전하게 액세스하는 데 사용할 수있는 인터페이스로 데이터 (또는 상태)를 캡슐화하여 일관성 있고 유효하게 유지하는 것을 의미합니다.

이것을 MS Word와 같이 생각하십시오. MS Word는 문서 모델을 메모리에 저장합니다 (문서 상태). 버튼, 도구, 키보드 명령 등 사용자가 문서를 수정하는 데 사용할 수있는 인터페이스를 제공합니다. 그러나 해당 문서를 유지 (저장)하도록 선택하면 키 누르기 세트가 아닌 내부 상태가 저장됩니다. 마우스 클릭으로 생성됩니다.

객체의 내부 상태를 저장하면 캡슐화가 중단되지 않습니다. 그렇지 않으면 캡슐화의 의미와 그 이유를 실제로 이해하지 못합니다. 그것은 실제로 객체 직렬화와 같습니다.

이러한 이유로, 대부분의 경우, 액세서가 아닌 필드를 유지하는 것이 적절합니다. 이는 객체가 저장된 방식대로 데이터베이스에서 객체를 정확하게 재생성 할 수 있음을 의미합니다. 원본을 만들 때와 데이터베이스에 저장하기 전에 원본에서 수행되었으므로 유효성 검사가 필요하지 않습니다 (하나님이 금지하지 않는 한 DB에 잘못된 데이터를 저장하고 있습니다! 마찬가지로 객체가 저장되기 전에 이미 계산되었으므로 값을 계산할 필요가 없습니다. 오브젝트는 오브젝트가 저장되기 전에 수행 된 방식대로 보여야합니다. 실제로 게터 / 세터에 추가 항목을 추가하면 실제로 원본의 정확한 사본이 아닌 것을 다시 만들 위험이 높아 집니다.

물론이 기능은 이유로 추가되었습니다. 접근자를 유지하기위한 유효한 사용 사례가있을 수 있지만 일반적으로 드물게 나타납니다. 예를 들어 계산 된 값을 유지하지 않으려는 경우가 있지만 값의 getter에서 요청시 값을 계산하지 않는 이유를 질문하거나 게터에서 게으르게 초기화하는 것이 좋습니다. 개인적으로 나는 어떤 유스 케이스도 생각할 수 없으며, 여기에 대한 답변 중 "소프트웨어 엔지니어링"답변은 없습니다.


9
소프트웨어 엔지니어링 해답은 접근자를 사용하는 것이 DRY를 위반하는 것입니다.
sourcedelica 2016 년

1
@Martin 귀하의 답변의 마지막 단락에 대한 후속 질문이 있습니다. "계산 된 값을 유지하지 않으려는 경우를 예로들 수 있습니다." 속성 기반 액세스를 통해 계산 된 값을 유지하지 않으려면 어떻게해야합니까? 나는 당신이 그렇게하지 말 것을 주장하지만 나는 여기서 요점을 얻지 못했습니다. 설명해 주시겠습니까?
Geek

4
@Geek 이제 다시 읽었으므로 완전히 확신 할 수는 없습니다. 이 답변을 쓴 지 2 년이 지났습니다. 더 좋은 예는 레거시 데이터베이스로 작업하는 곳일 수 있으며 데이터는 개체 모델과 다른 방식으로 표시됩니다. 접근자는 두 데이터베이스 간의 매핑을 제공 할 수 있습니다.
Martin

23
접근자를 매핑하는 좋은 사용 사례는 지속성 구현과 관련이없는 타사 엔터티 클래스의 하위 클래스에 매핑 정보를 추가해야하는 경우입니다. 필드는 해당 클래스에서 비공개이므로 접근자를 재정의하고 매핑 주석을 추가해야합니다. 또 다른 옵션은 XML 매핑을 사용하는 것이지만 일부 작업은 매우 어렵습니다. 따라서 주석을 원하고 타사 클래스를 매핑하려면 하위 클래스를 분류하고 접근 자에 주석을 추가하는 것이 좋습니다.
Elnur Abdurrakhimov

5
@ElnurAbdurrakhimov 우리는 훌륭한 예입니다. 감사.
Martin

79

각 속성에 대해 getter / setter를 제공하지 않아도되므로 필드 액세스를 선호합니다.

Google을 통한 빠른 설문 조사에 따르면 필드 액세스가 대부분 (예 : http://java.dzone.com/tips/12-feb-jpa-20-why-accesstype )이라고합니다.

필드 액세스는 Spring에서 권장하는 관용구라고 생각하지만 백업을위한 참조를 찾을 수 없습니다.

거기에 성능을 측정하려고 시도하고 "차이가 없다"는 결론에 도달 관련 SO 질문 이 있습니다.


엔티티에 setter getter를 제공하지 않으면 해당 필드의 사용은 무엇입니까 ... 어플리케이션에서 사용할 수 없으며 becuase 필드는 비공개입니다.
anshulkatta

1
귀하의 필드에 게터와 세터를 제공하지 않는 것이 좋지 않습니까? 공개 필드를 가정하고 있기 때문에 여기에 내 의견이 항상 옳은 것은 아니라고 생각합니다.
Mathijs Segers

3
@anshulkatta 나는 캡슐화의 모든 것이므로 귀하의 질문을 정말로 해결해야한다고 생각합니다. 이상적으로는 모든 필드가 비공개이어야하며 가능한 경우 게터 나 세터가 없어야합니다. 이는 원하는 수준의 캡슐화입니다. 비밀번호 검사기를 고려하십시오. 2 개의 개인 필드 passwordHash 및 failedAttempts. 둘 다 getter 또는 setter가없는 개인용 일 수 있습니다. 그것들은 bool checkPassword (string password)에 의해 사용되며, 해시, passwordHash를 검사 한 다음 failedAttempts를 업데이트하고 결과를 반환합니다. 다른 코드가이 두 필드에 액세스 할 필요가 없습니다.
Martin

2
@anshulkatta OOP에서 getter와 setter는 안티 패턴이며 절차 적 프로그래밍에서 왔으며 클래스가 있으면 캡슐화 원칙을 위반하고 많은 상용구 코드, 즉 동일한 종류의 코드를 생성합니다. 코드가 반복해서 반복되었습니다. 객체는 불변이어야하며, 속성을 수정해야하는 경우 속성 값을 반환하는 것 이상의 작업을 수행하는 메서드를 통해 수행해야합니다.
Uriel Arvizu 16:27에

별로. 이 경우 "반 패턴"은 교리가 아니라 의견의 문제입니다. 그럼에도 불구하고, 필드 액세스는 여전히 선호된다. 더 나은 아이디어는 ORM 솔루션에서 완전히 벗어나는 것입니다. 적절한 SQL을 작성하는 방법을 배우십시오.
duffymo

38

속성 접근자를 사용하는 상황이 있습니다. 8 개의 구체적인 서브 클래스로 상속 할 수있는 구현의 장점이 많은 GENERIC 추상 클래스가 있다고 상상해보십시오.

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
 }

이제이 클래스에 어떻게 주석을 달아야합니까? 답은이 시점에서 대상 엔터티를 지정할 수 없으므로 필드 또는 속성 액세스로 주석을 달 수 없습니다. 구체적인 구현에 주석을 달아야합니다. 그러나 지속 속성이이 슈퍼 클래스에 선언되어 있으므로 서브 클래스에서 속성 액세스를 사용해야합니다.

필드 액세스는 추상 일반 슈퍼 클래스가있는 응용 프로그램의 옵션이 아닙니다.


2
감동. 나는 그것을 생각하지 않았다. 나는 Hibernate가 이것에 대한 미친 SQL을 쫓아 내기를 걸었다.
Joseph Lust

8
이 문제는 속성에 주석을 달지 않고는 기계적으로 해결하기 어려운 것처럼 들리지만, 내가 구현하고 싶었던 많은 구현을 가진 추상 일반 클래스가 필요한 경우는 없었습니다. 일반적으로 클래스 재사용을 생성하여 객체를 다형성으로 만들고 (일반적인 종류의 나누기) 코드 재사용만을위한 것은 아닙니다. 그리고 "많은 구현과 많은 구현"이 SRP를 위반하는 경우가 많으며,이 경우 별도의 클래스로 이동시킬 수 있습니다. 이 사용 사례를보다 명확하게하는 구체적인 예가 있습니까?
Merlyn Morgan-Graham

내가 가지고있는 구체적인 예는 내 응용 프로그램이며 500 문자 주석으로 설명 할 수 없습니다. ;-)
HDave

3
당신은 사용 abstract T getOneThing()하고 abstract void setOneThing(T thing), 현장 접근을 사용합니다.
Arturo Volpe

33

나는 속성 접근자를 선호하고 사용하는 경향이 있습니다.

  • 필요한 경우 (허용 된 답변에 언급 된대로) 논리를 추가 할 수 있습니다.
  • foo.getId() 프록시를 초기화하지 않고 전화를 걸 수 있습니다 ( HHH-3718 이 해결 될 때까지 최대 절전 모드를 사용할 때 중요합니다 ).

약점:

  • 코드를 읽기 쉽도록 만듭니다. 예를 들어, 전체 클래스를 탐색하여 @Transient주변에 있는지 확인해야합니다.

그러나 "프록시"가없는 JPA 제공자를 사용하는 경우 "JPA 제공자가 귀하에게 부과하고 있습니다"라는 문제가 발생하지 않습니다.
Neil Stockton

13

실제로는 특정한 경우에 따라 다릅니다. 두 가지 옵션을 모두 사용할 수 있습니다. IMO는 세 가지 사례로 요약됩니다.

  1. setter에는 데이터베이스에서 인스턴스를로드 할 때 실행해서는 안되는 몇 가지 논리가 있습니다. 예를 들어, 일부 값 유효성 검사는 setter에서 발생하지만 db에서 오는 데이터는 유효해야합니다 (그렇지 않으면 도달하지 못함 (:);이 경우 필드 액세스가 가장 적합합니다).
  2. setter에는 db에서 인스턴스를로드하는 동안에도 항상 호출해야하는 로직이 있습니다. 예를 들어, 초기화되는 속성은 계산 된 일부 필드의 계산에 사용됩니다 (예 : 속성-화폐 금액, 계산 된 속성-동일한 인스턴스의 총 여러 통화 속성). 이 경우 속성 액세스가 필요합니다.
  3. 위의 경우 중 어느 것도 해당되지 않습니다-두 옵션 모두 적용 가능합니다. 일관성을 유지하십시오 (이 상황에서 필드 액세스가 선택되면 비슷한 상황에서 항상 사용하십시오).

나는 최대 절전 모드를 처음 사용하고 동일한 질문으로 고심하고 있습니다. 이 게시물이 가장 명확한 대답이라고 생각합니다. 감사합니다.
Sam Levin

12

값을 설정하는 것 (예 : 암호화 또는 계산)보다 세터에서 더 많은 작업을 수행하려는 경우 게터에 대한 필드 액세스 및 NOT 주석 (프로퍼티 액세스)을 강력히 권장합니다.

속성 액세스의 문제점은 객체가로드 될 때 setter도 호출된다는 것입니다. 이것은 우리가 암호화를 도입하고 싶을 때까지 몇 달 동안 나에게 잘 작동했습니다. 우리의 유스 케이스에서는 setter에서 필드를 암호화하고 getter에서 필드를 해독하려고했습니다. 속성 액세스의 문제는 Hibernate가 객체를로드 할 때 필드를 채우기 위해 setter를 호출하여 암호화 된 값을 다시 암호화한다는 것입니다. 이 포스트는 또한 이것을 언급합니다 : Java Hibernate : 그것을 호출하는 사람에 따라 다른 속성 세트 함수 동작

필드 액세스와 속성 액세스의 차이점을 기억하기 전까지는 두통이 발생했습니다. 이제 모든 주석을 속성 액세스에서 필드 액세스로 옮겼으며 이제 제대로 작동합니다.


예-속성 액세스를 사용하면 실제로 필드 값을 설정하는 것 외에 세터에서 아무것도 할 수 없다는 것을 알았습니다.
HDave

2
+1 게터 / 세터로부터 멀리하십시오. 나는 projectlombok.org를 사용 하고 개발자들에게 숨겨져 있습니다.
bhantol

11

다음과 같은 이유로 필드 액세스를 선호합니다.

  1. 속성 액세스가 같음 / 해시 코드를 구현할 때 매우 불쾌한 버그로 이어질 수 직접적으로 필드를 참조 (자신의 게터를 통해 반대). 프록시가 게터에 액세스 할 때만 초기화되기 때문에 직접 필드 액세스는 단순히 null을 반환하기 때문입니다.

  2. 속성 액세스는 모든 주석을하도록 요구 유틸리티 메소드 등 (예하는 AddChild /로 removeChild) @Transient.

  3. 필드 액세스를 통해 게터를 전혀 노출시키지 않으면 서 @Version 필드를 숨길 수 있습니다. 게터는 또한 세터를 추가하게 할 수 있으며 version필드를 수동으로 설정해서는 안됩니다 (매우 불쾌한 문제가 발생할 수 있음). 모든 버전 증분은 OPTIMISTIC_FORCE_INCREMENT 또는 PESSIMISTIC_FORCE_INCREMENT 명시 적 잠금을 통해 트리거되어야합니다 .


1. 현장 접근 전략은이를 어떻게 방지합니까? 이것은 액세스 스타일에 관계없이 프록시의 일반적인 함정으로 보입니다. 2. 유틸리티 게터일까요? (그러나 어쨌든 좋은 주장). 3.version 필드에 접근자를 노출 시키는 것은 분리 된 엔티티 대신 DTO가 사용되는 상황에서 종종 유용합니다.
Dragan Bozanovic 2016 년

1. 프록시가 초기화되는시기. 2. 100 % 확실합니다. 3. 그것은 유효한 포인트입니다.
Vlad Mihalcea 2016 년

내 무지와 가능한 텍스트 해석 부족을 용서하십시오 (나는 영어 원어민이 아닙니다). 명확히하기 위해, 필드 액세스는 getter / setter 메소드가 필요하지 않을 때입니다. 따라서 POJO의 경우 전체적으로 사용되며 필드는 공개입니까? 그러나 첫 번째 주제에서 무언가를 말하면 링크 된 블로그 게시물에서 반대 의견을 말합니다. 내가 이해 한 것은 프록시와 필드 액세스를 사용할 때 평등을 사용할 수 없다는 것입니다.
MaikoID

필드 액세스는 Hibernate가 리플렉션을 통해 필드를 사용하여 엔티티 속성을 읽는 것을 의미합니다. 자세한 내용은 Hibernate 사용 설명서 의 액세스 유형 섹션을 확인하십시오 .
Vlad Mihalcea

7

ORM이 수행하는 경우에도 필드를 업데이트하면 캡슐화가 직접 중단되므로 속성에 주석을 추가하는 것이 좋습니다.

다음은 어디에서 화상을 입는 지에 대한 좋은 예입니다. 같은 위치 (필드 또는 속성)에서 최대 절전 모드 유효성 검사기 및 지속성을위한 주석을 원할 것입니다. 필드에 주석이 달린 최대 절전 모드 유효성 검사기 유효성 검사를 테스트하려는 경우 엔터티 모의를 사용하여 단위 테스트를 유효성 검사기 만 분리 할 수 ​​없습니다. 아야.


2
그래서 접근 자에 대한 유효성 검사기 주석과 필드에 대한 지속성 주석을 추가해야합니다.
fishbone

6

부동산 접근과 현장 접근은 게으른 초기화와 관련하여 미묘하게 다르다고 생각합니다.

2 개의 기본 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()그렇지는 않습니다.


재미있다! :) 그러나 그것은 구현에 따른 행동입니다. 나
Vladimir Dyuzhev

그렇습니다. 이것은 영속 클래스 만 계측되기 때문입니다. 그러나 id 필드는 종종 비즈니스 가치가 없으며 접근자가 필요하지 않은 필드이기 때문에 까다로운 작업입니다.
Maurice Perry

6

필드 기반 액세스를 선택하는 가장 중요한 이유를 요약 해 보겠습니다. 더 자세히 알아 보려면 내 블로그 에서 JPA 및 최대 절전 모드의 액세스 전략 –이 필드 또는 속성 액세스 중 어떤 것이 더 좋습니까?

필드 기반 액세스가 훨씬 더 나은 옵션입니다. 여기에 5 가지 이유가 있습니다.

이유 1 : 코드의 가독성 향상

필드 기반 액세스를 사용하는 경우 엔티티 속성에 맵핑 주석으로 주석을 달 수 있습니다. 모든 엔터티 속성의 정의를 클래스 상단에 배치하면 모든 속성 및 매핑에 대한 비교적 간단한보기를 얻을 수 있습니다.

이유 2 : 애플리케이션에서 호출해서는 안되는 getter 또는 setter 메소드를 생략하십시오.

필드 기반 액세스의 또 다른 장점은 지속성 제공자 (예 : Hibernate 또는 EclipseLink)가 엔티티 속성의 getter 및 setter 메소드를 사용하지 않는다는 것입니다. 즉, 비즈니스 코드에서 사용해서는 안되는 방법을 제공 할 필요가 없습니다. 생성 된 기본 키 속성 또는 버전 열의 세터 메소드의 경우가 가장 흔합니다 . 지속성 제공자는 이러한 속성의 값을 관리하므로 프로그래밍 방식으로 설정하지 않아야합니다.

이유 3 : 게터 및 세터 메소드의 유연한 구현

퍼시 스턴트 제공자는 getter 및 setter 메소드를 호출하지 않으므로 외부 요구 사항을 충족하지 않아도됩니다. 원하는 방식으로 이러한 메소드를 구현할 수 있습니다. 이를 통해 비즈니스 별 유효성 검사 규칙을 구현하거나 추가 비즈니스 논리를 트리거하거나 엔터티 특성을 다른 데이터 형식으로 변환 할 수 있습니다.

예를 들어,이를 사용 하여 선택적 연관 또는 속성을 Java로 랩핑 할 수 있습니다 .Optional

이유 4 : 유틸리티 메소드를 다음과 같이 표시 할 필요가 없습니다. @Transient

필드 기반 액세스 전략의 또 다른 장점은로 유틸리티 유틸리티에 주석을 달 필요가 없다는 것입니다 @Transient. 이 어노테이션은 지속성 제공자에게 메소드 또는 속성이 엔티티 지속 상태의 일부가 아님을 알려줍니다. 또한 필드 유형 액세스를 사용하면 엔티티 상태에 따라 지속 상태가 정의되므로 JPA 구현은 엔티티의 모든 메소드를 무시합니다.

이유 5 : 프록시 작업시 버그 방지

Hibernate는 느리게 페치 된 일대일 연관에 프록시를 사용 하여 이러한 연관의 초기화를 제어 할 수 있습니다. 이 방법은 거의 모든 상황에서 잘 작동합니다. 그러나 속성 기반 액세스를 사용하면 위험한 함정이 생깁니다.

프로퍼티 기반 액세스를 사용하는 경우, Hibernate는 getter 메소드를 호출 할 때 프록시 객체의 속성을 초기화합니다. 비즈니스 코드에서 프록시 객체를 사용하는 경우 항상 그렇습니다. 그러나 상당수의 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.PROPERTYJavaBean 접근 자 대신 (기본값) 을 사용 하고 개인 필드에 주석을 달 경우, 필드 이름은 JavaBean 등록 정보 이름과 일치해야합니다. 그러나 JavaBean 액세서에 주석을 달면 이름이 일치하지 않아도됩니다. 마찬가지로 AccessType.FIELD필드 대신 JavaBean 접근자를 사용 하고 주석을 달 경우 필드 이름도 JavaBean 등록 정보 이름과 일치해야합니다. 이 경우 필드에 주석을 달면 일치하지 않아도됩니다. 에 대한 JavaBean 접근 자 AccessType.PROPERTY와 필드에 주석을 달고 일관성을 유지하는 것이 가장 좋습니다 AccessType.FIELD.

JPA 속성 주석과 JPA 필드 주석을 동일한 엔터티에 혼합해서는 안됩니다. 그렇게하면 지정되지 않은 동작이 발생하고 오류가 발생할 가능성이 큽니다.


2

우리는 아직있다

이전 프레젠테이션이지만 Rod는 속성 액세스에 대한 주석이 빈혈 도메인 모델을 장려하고 주석을 달기위한 "기본"방법이되어서는 안된다고 제안합니다.


2

필드 액세스를 선호하는 또 다른 요점은 컬렉션에 setter를 노출시켜야한다는 것입니다. 잠재적 인 컬렉션 인스턴스를 Hibernate가 관리하지 않는 객체로 변경하면 데이터 일관성이 확실히 손상되므로 나쁘지 않습니다.

따라서 기본 생성자의 빈 구현으로 보호 필드를 초기화하고 getter 만 노출시키는 컬렉션을 선호합니다. 같은 그런 다음, 단지 관리 운영 clear(), remove(), removeAll()등 변화의 최대 절전 모드가 인식하게하지 않습니다이 가능합니다.


세터를 보호 할 수 있으므로 어떤 것도 노출시키지 마십시오. 또한 이러한 세터는 구현되는 인터페이스의 일부가 아니므로 공개 된 경우에도 쉽게 액세스 할 수 없습니다.
HDave

2

나는 필드를 선호하지만 한 가지 상황에 처해있어 getters에 주석을 배치해야합니다.

Hibernate JPA 구현 @Embedded으로 필드에서 작동하지 않는 것 같습니다. 그래서 그것은 게터에 가야합니다. 그리고 일단 그것을 getter에 넣으면 다양한 @Column주석이 getter에도 적용되어야합니다. (저는 Hibernate가 여기에서 필드와 게터를 혼합하는 것을 원하지 않는다고 생각합니다.) 일단 @Column한 클래스에서 게터를 착용 하면 전체적으로 그렇게하는 것이 합리적입니다.


2

필드 접근자를 선호합니다. 코드가 훨씬 깨끗합니다. 모든 주석은 클래스의 한 섹션에 배치 할 수 있으며 코드를 훨씬 쉽게 읽을 수 있습니다.

속성 접근 자에 대한 또 다른 문제가 있습니다. 클래스에 getXYZ 메소드가 영구적 속성과 관련이있는 것으로 주석 처리되지 않은 경우, 최대 절전 모드는 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 명칭 (공장이 대부분의 속성을 설정 함)을 설정할 수 있습니다.




1

엔티티 bean을 작성하고 getter 주석을 사용했습니다. 우리가 겪은 문제는 이것입니다. 일부 엔티티는 언제 업데이트 할 수 있는지에 관한 복잡한 속성을 가지고 있습니다. 솔루션은 실제 값이 변경되었는지 여부와 변경이 허용되는지 여부를 결정하는 비즈니스 로직을 각 세터에 포함시키는 것이 었습니다. 물론 최대 절전 모드는 항상 속성을 설정할 수 있으므로 두 그룹의 세터로 끝납니다. 아주 못생긴.

이전 게시물을 읽으면서 엔티티 내부에서 속성을 참조하면 컬렉션이로드되지 않는 문제가 발생할 수 있음을 알았습니다.

결론적으로, 나는 앞으로 필드에 주석을 달아 줄 것입니다.


0

보통 콩은 POJO이므로 어쨌든 접근자가 있습니다.

따라서 질문은 "어느 쪽이 더 낫습니까?"가 아니라 단순히 "필드 액세스를 언제 사용합니까?"입니다. 그리고 대답은 "현장에 세터 / 게터가 필요 없을 때!"입니다.


4
당신이 하나를 선택해야한다 - 문제는 당신이 POJO 필드 액세스 및 속성 액세스를 혼합 할 수 있다는 것입니다
마틴 OConnor

정말? 잊어 버렸을 것입니다. 어쨌든, 나는 항상 POJO와 d 접근자를 사용합니다.
블라디미르 듀우 예프

JPA 2.0 (이 질문이 나오지 않았을 때)에서는 이제 @AccessType 주석을 사용하여 액세스 유형을 혼합 할 수 있습니다.
mtpettyp

0

나는 이것에 대해 생각하고 방법 accesor를 선택한다

왜?

필드와 메 토스 accesor가 동일하기 때문에 나중에로드 필드에 논리가 필요하면 필드에 배치 된 모든 주석을 이동합니다.

문안 인사

그루브 하트


0

클래스를 더 깨끗하게 만들려면 필드에 주석을 넣고 @Access (AccessType.PROPERTY)를 사용하십시오.



0

AccessType.PROPERTY : EJB 지속성 구현은 JavaBean "setter"메소드를 통해 클래스에 상태를로드하고 JavaBean "getter"메소드를 사용하여 클래스에서 상태를 검색합니다. 이것이 기본값입니다.

AccessType.FIELD : 상태는 클래스의 필드에서 직접로드 및 검색됩니다. JavaBean "getters"및 "setters"를 작성할 필요가 없습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.