휴지 상태 주석 - 필드 액세스와 속성 액세스 중 어느 쪽이 더 좋습니까?
이 질문은 휴지 상태 주석 배치 질문과 관련이 있습니다.
하지만 어떤 게 더 나은지 알고 싶어요?속성을 통한 액세스 또는 필드를 통한 액세스각각의 장점과 단점은 무엇입니까?
둘 다 인수가 있지만 대부분은 특정 사용자 요건인 "로직을 추가해야 하는 경우" 또는 "xxxx 캡슐화를 중단합니다"에서 비롯됩니다.하지만, 아무도 그 이론에 대해 진정으로 논평을 하지 않았고, 적절한 논거를 제시하지 않았다.
휴지 상태/J에 대해서PA는 객체를 유지할 때 실제로 수행합니다.이것은 객체의 상태를 유지하는 것입니다.즉, 복제하기 쉬운 방법으로 보관하는 것입니다.
캡슐화란 무엇입니까?캡슐화는 데이터(또는 상태)를 애플리케이션/클라이언트가 데이터에 안전하게 액세스하기 위해 사용할 수 있는 인터페이스로 캡슐화하는 것을 의미합니다.이 인터페이스를 통해 데이터(또는 상태)를 일관되고 유효하게 유지합니다.
이것을 MS Word라고 생각해 주세요.MS Word는 메모리의 문서 모델인 문서 상태를 유지합니다.사용자가 문서를 수정하는 데 사용할 수 있는 인터페이스(단추, 도구, 키보드 명령어 세트 등)를 제공합니다.그러나 해당 문서를 유지(저장)하도록 선택하면 문서를 생성하는 데 사용된 키 누르기와 마우스 클릭 집합이 아닌 내부 상태가 저장됩니다.
개체의 내부 상태를 저장해도 캡슐화가 중단되지 않습니다. 그렇지 않으면 캡슐화의 의미와 캡슐화가 존재하는 이유를 제대로 이해하지 못합니다.그것은 정말로 객체 연재물 같다.
따라서 대부분의 경우 ACCESSOR가 아닌 필드를 유지하는 것이 적절합니다.즉, 객체가 저장된 그대로 데이터베이스에서 정확하게 다시 생성될 수 있습니다.검증은 생성 시 원본에서 수행되었으며 데이터베이스에 저장되기 전에 수행되었기 때문에 필요하지 않습니다(예: 잘못된 데이터를 DB에 저장하는 것을 금지합니다!!!).마찬가지로 오브젝트가 저장되기 전에 이미 계산되었기 때문에 값을 계산할 필요가 없습니다.오브젝트는 저장 전 모습 그대로 표시되어야 합니다.실제로 getters/setters에 추가 내용을 추가하면 원본과 완전히 다른 내용을 다시 작성할 위험이 높아집니다.
물론 이 기능이 추가된 것은 이유가 있습니다.액세스 장치를 유지하는 데 몇 가지 유효한 사용 사례가 있을 수 있지만, 일반적으로 이러한 사례는 거의 없습니다.예를 들어 계산된 값이 유지되는 것을 피하고 싶은 경우가 있습니다.단, 값의 getter에서 온 디맨드로 계산하거나 getter에서 천천히 초기화하지 않는 이유를 묻고 싶은 경우도 있습니다.개인적으로 좋은 사용 사례는 생각할 수 없습니다.또, 여기에서는, 「소프트웨어 엔지니어링」이라고 하는 답을 얻을 수 없습니다.
필드 액세스를 선호합니다. 그래야 각 자산에 getter/setter를 제공할 필요가 없기 때문입니다.
Google을 통한 간단한 설문조사에 따르면 필드 액세스가 대부분입니다(예: http://java.dzone.com/tips/12-feb-jpa-20-why-accesstype)).
Field Access는 Spring이 추천하는 관용어라고 생각합니다만, 그것을 뒷받침할 참고 자료를 찾을 수 없습니다.
퍼포먼스를 측정하려다 '차이가 없다'는 결론에 도달한 관련 SO 질문이 있습니다.
여기 당신이 부동산 접근업자를 이용해야 하는 상황이 있습니다.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
}
이 클래스에 주석을 다는 방법은 무엇입니까?이 시점에서는 대상 엔티티를 지정할 수 없기 때문에 필드 또는 속성 액세스로 주석을 달 수 없습니다.구체적인 구현에 주석을 달아야 합니다.그러나 지속 속성은 이 슈퍼 클래스에서 선언되므로 하위 클래스에서 속성 액세스를 사용해야 합니다.
추상적인 일반 슈퍼클래스가 있는 응용 프로그램에서는 필드 액세스가 허용되지 않습니다.
나는 부동산 액세스 업체를 선호하고 사용하는 경향이 있다.
- 필요에 따라 논리를 추가할 수 있습니다(승인된 답변에 기재되어 있습니다).
- 하면 제가 화할수수수 it it it라고 부를 수 요.
foo.getId()
(HH-3718이 해결될 때까지 하이버네이트를 사용할 때 중요).
결점:
- , 수업 경우 등이 있습니다. 예를 들어, 당신은 전체 클래스를 브라우즈하여 다음 항목이 있는지 확인해야 합니다.
@Transient
그 근처에요.
필요할 때 언제든지 비즈니스 로직을 추가할 수 있기 때문에 접근자를 선호합니다.다음은 예를 제시하겠습니다.
@Entity
public class Person {
@Column("nickName")
public String getNickName(){
if(this.name != null) return generateFunnyNick(this.name);
else return "John Doe";
}
}
또한 다른 libs를 혼합에 넣으면(예를 들어 JSON 변환 lib, Bean Mapper, Dozer 또는 getter/setter 속성에 기반한 다른 bean mapping/cloning lib 등) lib가 퍼시스텐스 매니저와 동기화됨을 보증합니다(둘 다 getter/setter 사용).
필드 기반 액세스를 선택하는 가장 중요한 이유를 요약해 보겠습니다.더 자세히 알아보려면 제 블로그에서 다음 기사를 읽어보세요.JPA와 휴지 상태에서의 액세스 전략– 필드 액세스와 프로퍼티 액세스 중 어느 쪽이 좋은가요?
필드 기반 액세스가 훨씬 더 나은 옵션입니다.여기에는 5가지 이유가 있습니다.
이유 1: 코드 가독성 향상
필드 기반 액세스를 사용하는 경우 도면요소 속성에 매핑 주석을 추가합니다.모든 엔티티 속성의 정의를 클래스 맨 위에 배치하면 모든 속성과 그 매핑을 비교적 간략하게 볼 수 있습니다.
이유 2: 어플리케이션에서 호출해서는 안 되는 getter 메서드 또는 setter 메서드를 생략합니다.
필드 기반 액세스의 또 다른 장점은 지속성 공급자인 Hibernate 또는 Eclipse Link가 엔티티 속성의 getter 및 setter 메서드를 사용하지 않는다는 것입니다.즉, 비즈니스 코드에서 사용해서는 안 되는 방법을 제공할 필요가 없습니다.이것은 생성된 프라이머리 키 속성 또는 버전 열의 세터 메서드의 경우가 대부분입니다.지속성 공급자는 이러한 속성의 값을 관리하므로 프로그래밍 방식으로 설정하지 마십시오.
이유 3: getter 및 setter 방식의 유연한 구현
지속성 공급자는 getter 메서드와 setter 메서드를 호출하지 않기 때문에 외부 요건을 충족하도록 강요받지 않습니다.이러한 메서드는 임의의 방법으로 구현할 수 있습니다.이를 통해 비즈니스별 검증 규칙을 구현하거나 추가 비즈니스 로직을 트리거하거나 엔티티 속성을 다른 데이터 유형으로 변환할 수 있습니다.
예를 들어, 이를 사용하여 임의의 어소시에이션 또는 Atribute를 Java로 랩할 수 있습니다.
4:을 4로 가 없습니다.@Transient
또에 '어태닝'을 필요가 입니다.@Transient
이 주석은 지속성 공급자에게 메서드 또는 속성이 엔티티 지속성 상태의 일부가 아님을 알려줍니다.또한 필드 유형 액세스에서는 영속적인 상태는 엔티티의 Atribut에 의해 정의되기 때문에 JPA 구현에서는 엔티티의 모든 메서드가 무시됩니다.
이유 5: 프록시 사용 시 버그를 피하기 위해
휴지 상태에서는, 이러한 어소시에이션의 초기화를 제어할 수 있도록, 어소시에이션의 취득이 늦어지는 어소시에이션의 프록시를 사용합니다.이 접근방식은 거의 모든 상황에서 잘 작동합니다.하지만 재산 기반 접근을 이용한다면 위험한 함정을 초래할 수 있습니다.
속성 기반 액세스를 사용하는 경우 getter 메서드를 호출하면 프록시 개체의 속성이 최대 절전 모드로 초기화됩니다.비즈니스 코드에서 프록시 개체를 사용하는 경우 항상 그렇습니다.그러나 상당수의 동등 및 hashCode 구현은 속성에 직접 액세스합니다.프록시 Atribute 중 하나에 처음 액세스하는 경우에도 이러한 Atribute는 초기화되지 않습니다.
다음과 같은 이유로 필드 액세스를 사용하는 것이 좋습니다.
equals/hashCode 를 실장하고 필드를 직접 참조할 때(게터를 통해 참조하는 것이 아니라) 속성 액세스에 의해 매우 심각한 버그가 발생할 수 있습니다.이는 프록시가 getter에 액세스할 때만 초기화되며 직접 필드 액세스는 단순히 null을 반환하기 때문입니다.
속성 액세스에서는 다음과 같이 모든 유틸리티 메서드(예: addChild/removeChild)에 주석을 달아야 합니다.
@Transient
.에서는, 「필드의 액세스」나 「의 액세스」를 수 있습니다.
@Version
게터를 전혀 노출시키지 않음으로써 필드를 만듭니다.도 있고 getter는 setter를 할 수도 있습니다.version
필드를 수동으로 설정하지 마십시오(매우 심각한 문제가 발생할 수 있음).모든 버전 인크리먼트는 또는 명시적인 잠금을 통해 트리거해야 합니다.
그것은 특정 케이스에 따라 다릅니다.두 가지 옵션 모두 이유가 있습니다.IMO는 세 가지 경우로 요약됩니다.
- setter에는 데이터베이스에서 인스턴스를 로드할 때 실행해서는 안 되는 로직이 있습니다.예를 들어 값 검증은 setter에서 이루어지지만 db에서 전송된 데이터는 유효해야 합니다(이 경우 field access가 가장 적절합니다).
- setter는 db에서 인스턴스를 로드하는 동안에도 항상 호출되어야 하는 논리를 가지고 있습니다.예를 들어 초기화되는 속성은 계산필드의 계산에 사용됩니다(예를 들어, 같은 인스턴스의 금전적 금액, 계산된 속성, 총 몇 가지 금전적 속성). 이 경우 속성 액세스가 필요합니다.d.
- 위의 경우 중 어느 것도 해당되지 않습니다.그러면 두 가지 옵션이 모두 해당되므로 일관성을 유지하십시오(즉, 이 상황에서 필드 액세스가 선택되는 경우 항상 동일한 상황에서 필드 액세스를 사용하십시오).
값을 설정하는 것(암호화 또는 계산 등)보다 세터에서 더 많은 작업을 수행할 경우 게터(속성 액세스)에 대한 주석을 사용하지 않고 필드 액세스를 권장합니다.
속성 액세스의 문제는 오브젝트가 로드될 때 세터도 호출된다는 것입니다.암호화를 도입하기 전까진 몇 달 동안 잘 작동했어요.이 사용 예에서는 설정기에서 필드를 암호화하고 getter에서 필드를 복호화하려고 했습니다.현재 속성 접근에 관한 문제는 Hibernate가 오브젝트를 로드했을 때 셋터를 호출하여 필드를 채우고 암호화된 값을 다시 암호화하는 것이었습니다.이 투고에서는, Java 휴지 상태: 호출하는 사용자에 따라 다른 속성 집합 함수 동작
현장접근과 재산접근의 차이를 기억하기 전까지는 두통이 있었습니다.이제 모든 주석을 속성 액세스에서 필드 액세스로 이동했고 이제 정상적으로 작동합니다.
ORM이 캡슐화를 수행하더라도 필드를 직접 업데이트하면 캡슐화가 해제되므로 속성에 주석을 다는 것이 더 낫다고 생각합니다.
여기에서는, 하이버네이션 검증자와 퍼시스텐스를 같은 장소(필드 또는 속성)에 배치하기 위한 주석을 사용하는 것을 추천합니다.필드에 주석이 달린 휴지 상태 검증 기능을 테스트하려면 엔티티의 모의 테스트를 사용하여 장치 테스트를 검증기에만 분리할 수 없습니다.아야.
느린 초기화에 관해서는 부동산 액세스와 필드 액세스는 미묘하게 다르다고 생각합니다.
2개의 기본 콩에 대해 다음 매핑을 고려합니다.
<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()
지지않않않않
기본적으로 JPA 공급자는 엔티티 필드의 값에 액세스하고 엔티티의 JavaBean 속성 액세스자(getter) 및 뮤테이터(setter) 메서드를 사용하여 이러한 필드를 데이터베이스 열에 매핑합니다.따라서 엔티티 내의 개인 필드의 이름과 유형은 JPA에 중요하지 않습니다.JPA JavaBean beanbeanbean 。하려면 , 「 」를 합니다.@javax.persistence.Access
주석: JPA 공급자가 채택해야 하는 접근 방법론을 명시적으로 지정할 수 있습니다.
@Entity
@Access(AccessType.FIELD)
public class SomeEntity implements Serializable
{
...
}
액세스에 사용 가능한 옵션enum 유형은 PROPERTY(기본값) 및 FILD입니다.Property를 사용하면 공급자는 JavaBean 속성 메서드를 사용하여 필드 값을 가져오고 설정합니다.FILD는 공급자가 인스턴스 필드를 사용하여 필드 값을 가져오고 설정하도록 합니다.특별한 이유가 없는 한 기본값을 그대로 사용하고 JavaBean 속성을 사용하는 것이 좋습니다.
이러한 속성 주석은 개인 필드 또는 공용 접근자 메서드에 추가할 수 있습니다.「 」를 사용하고 AccessType.PROPERTY
(JavaBean) JavaBean을 사용합니다. 자바빈 JavaBean 을 달 경우 . '우리'를 사용하면,AccessType.FIELD
필드 대신 JavaBean 접근자에 주석을 달아 필드 이름도 JavaBean 속성 이름과 일치해야 합니다.이 경우 필드에 주석을 달면 일치할 필요가 없습니다.JavaBean 을 유지하고 .AccessType.PROPERTY
및드의 AccessType.FIELD
.
JPA 속성 주석과 JPA 필드 주석을 동일한 엔티티에 혼재시키지 않는 것이 중요합니다.이렇게 하면 지정되지 않은 동작이 발생하여 오류가 발생할 가능성이 높습니다.
오래된 프레젠테이션이지만 Rod는 속성 액세스에 대한 주석이 빈약한 도메인 모델을 장려하므로 주석을 다는 "기본" 방식이 되어서는 안 된다고 제안합니다.
필드 액세스에 유리한 또 다른 포인트는 콜렉션에 대해 세터를 공개하지 않으면 안 된다는 것입니다.또한 영속적인 콜렉션 인스턴스를 Hibernate에 의해 관리되지 않는 오브젝트로 변경하는 것은 데이터의 일관성을 확실히 해칠 수 있기 때문입니다.
따라서 컬렉션을 기본 컨스트럭터의 빈 구현으로 초기화하여 getter만 노출하는 보호 필드로 하는 것이 좋습니다. 다음, 관리 는 하다, 하다, 하다, 하다, 이런 식으로만 .clear()
,remove()
,removeAll()
hibernate가 변경내용을 하지 못하게 를 참조해 .
필드를 선호하지만 getter에 주석을 배치해야 하는 상황이 발생했습니다.
JPA에서는, 「JPA」를 합니다.@Embedded
이치노그래서 그건 더 빨리 진행되어야만 해.그리고 일단 그걸 게터 위에 올리면, 다양한 것들이@Column
구하다(하이버네이트) ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★.@Column
한 반의 getter에게, 그렇게 하는 것이 아마 이치에 맞을 것이다.
현장접근자를 선호합니다.암호가 훨씬 깨끗합니다.모든 주석을 클래스의 한 섹션에 배치할 수 있으며 코드를 읽기 훨씬 쉽습니다.
프로퍼티 액세스에 또 다른 문제가 있는 것을 발견했습니다.getX가 있는 경우클래스에서 영구 속성과 관련되지 않은 YZ 메서드는 hibernate로 인해 sql이 생성되어 해당 속성을 가져오려고 시도하므로 매우 혼란스러운 오류 메시지가 나타납니다.2시간이나 허비했다.이 코드는 작성하지 않았습니다.이전에는 항상 Field Accessor를 사용했기 때문에 이 문제는 발생하지 않았습니다.
이 앱에서 사용되는 휴지 상태 버전:
<!-- 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>
속성을 통한 액세스보다 필드를 통한 액세스를 선택해야 합니다.필드를 사용하여 송수신되는 데이터를 제한할 수 있습니다.via 속성을 사용하면 더 많은 데이터를 호스트로 보내고 G 단위(공장에서 대부분의 속성을 총 설정)를 설정할 수 있습니다.
보통 콩은 POJO이기 때문에 접근자가 있습니다.
따라서 문제는 "어느 것이 더 나은가?"가 아니라 "필드 액세스를 언제 사용할 것인가?"입니다.정답은 "현장에 세터/게터가 필요 없을 때!"입니다.
나는 동면시의 accesstype에 대해 같은 질문을 했고, 여기에서 몇 가지 답을 찾았다.
오브젝트 전체를 가져오지 않고 여기서 슬로우 초기화 및 필드 액세스를 해결했습니다.1 대 1: getId()로 휴지 상태
엔티티 콩을 만들고 getter 주석을 사용했습니다.문제는 이것입니다.일부 엔티티에는 갱신 가능한 타이밍에 관한 복잡한 규칙이 있습니다.해결책은 실제 값이 변경되었는지 여부와 변경되었을 경우 변경을 허용해야 하는지 여부를 결정하는 비즈니스 논리를 각 설정자에 설치하는 것이었습니다.물론 Hibernate는 항상 속성을 설정할 수 있기 때문에 결과적으로 두 그룹의 setter를 갖게 되었습니다.꽤 못생겼다.
이전 투고를 읽으면 엔티티 내부에서 속성을 참조하면 컬렉션이 로드되지 않는 문제가 발생할 수 있습니다.
결론적으로, 나는 미래에 그 필드에 주석을 다는 쪽으로 기울 것이다.
나는 이것에 대해 생각하고 메서드 액셀러레이터
왜요?
필드와 메토스 액세서는 동일하지만 나중에 로드 필드에 논리가 필요하면 필드에 배치된 모든 주석 이동을 저장합니다.
안부 전해요
그루하트
클래스를 깔끔하게 만들려면 필드에 주석을 넣은 다음 @Access(AccessType)를 사용합니다.속성)
둘 다:
EJB3 사양에서는 액세스할 요소 유형(즉, 속성 액세스를 사용하는 경우 getter 메서드, 필드 액세스를 사용하는 경우 필드)에 대한 주석을 선언해야 합니다.
https://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/ #filename-filename
액세스 타입속성: EJB 지속성 구현은 JavaBean "setter" 메서드를 통해 상태를 클래스에 로드하고 JavaBean "getter" 메서드를 사용하여 클래스에서 상태를 가져옵니다.이것이 기본값입니다.
액세스 타입필드: 상태는 클래스의 필드에서 직접 로드되고 검색됩니다.JavaBean "getters" 및 "setters"를 쓸 필요가 없습니다.
언급URL : https://stackoverflow.com/questions/594597/hibernate-annotations-which-is-better-field-or-property-access
'source' 카테고리의 다른 글
날짜 문자열이 해당 형식의 유효한 날짜인지 확인 (0) | 2022.11.19 |
---|---|
풀 URL 사용 시 PHP file_get_contents가 매우 느리다 (0) | 2022.11.19 |
javascript(또는 jQuery) 사용 후 :: before 및 :: 등의 CSS 유사 요소 선택 및 조작 (0) | 2022.11.18 |
LIMIT 오프셋에서 MySQL 함수를 사용할 수 있습니까? (0) | 2022.11.18 |
MySQL이 0을 유효한 자동 증분 값으로 사용하도록 강제하는 방법 (0) | 2022.11.18 |