Hibernate 관리 객체에 대한 최종 필드를 선언하는 방법이 있습니까?

StackOverflow https://stackoverflow.com/questions/912093

  •  06-09-2019
  •  | 
  •  

문제

나는 이제 막 Hibernate를 시작하고 있으며, 지금까지 내가 본 모든 예제는 Hibernate 문서에 있는 튜토리얼과 거의 비슷해 보입니다.

package org.hibernate.tutorial.domain;
import java.util.Date;

public class Event {

    private Long id;
    private String title;
    private Date date;

    public Event() {}

    /* Accessor methods... */
}

구체적으로:어떤 필드도 다음과 같이 선언되지 않았습니다. final, 그리고 Hibernate 프레임워크가 클래스를 인스턴스화하고 해당 필드를 설정할 수 있도록 인수 없는 생성자가 있어야 합니다.

하지만 문제는 이렇습니다 - 나는 정말 피할 수 있을 때마다 어떤 식으로든 내 클래스를 변경 가능하게 만드는 것을 좋아하지 않습니다(Java Practices:불변 객체는 이를 수행하는 데 매우 강력한 주장을 제시합니다.)그래서 각 필드를 '최종'으로 선언하더라도 Hibernate를 작동시킬 수 있는 방법이 있습니까??

나는 Hibernate가 클래스를 인스턴스화하기 위해 Reflection을 사용하므로 잘못된 생성자를 선택하거나 매개변수 중 하나에 잘못된 값을 전달할 위험을 감수하지 않고 일종의 생성자를 호출할 수 있어야 한다는 것을 이해합니다. 인수가 없는 생성자를 호출하고 각 필드를 한 번에 하나씩 설정합니다.그러나 불변 객체를 안전하게 인스턴스화할 수 있도록 Hibernate에 필요한 정보를 제공하는 것이 가능해야 하지 않나요?

public class Event {

    private final Long id;
    private final String title;
    private final Date date;

    public Event(@SetsProperty("id") Long id,
        @SetsProperty("title") String title,
        @SetsProperty("date") Date date) {

        this.id = id;
        this.title = title;
        this.date = new Date(date.getTime());
    }

    /* Accessor methods... */
}

그만큼 @SetsProperty 주석은 물론 허구이지만 손이 닿지 않는 곳에는 없는 것 같습니다.

도움이 되었습니까?

해결책

많은 운영이 변한 상태를 수행하기 때문에 최대 절전 모드의 사용 사례가 아닌 것 같습니다.

  • 병합 객체
  • 더러운 상태 점검
  • 플러싱 변경

즉, 불변성에 대해 걱정한다면 사본 구성 요인과 함께 물체 주위에 포장지를 제공하도록 선택할 수 있습니다.

public class FinalEvent {
    private final Integer id;

    public FinalEvent(Event event) {
        id = event.id;
    }
}

그래도 추가 작업을 의미합니다.


이제 내가 생각하고 있으므로 최대 절전 모드 세션은 일반적으로 스레드 바운드 이며이 공간은 최종 필드의 이점 - 안전한 출판물입니다.

최종 필드의 다른 이점은 무엇입니까?

다른 팁

불변의 물체는 상태를 수정하는 방법이없는 객체 (즉, 필드)를 의미합니다. 필드는 최종적 일 필요는 없습니다. 따라서 모든 돌연변이터를 제거하고 액세서 대신 필드 ACCE를 사용하도록 최대 절전 모드를 구성하거나 무의미한 생성자와 돌연변이를 더 이상 표시 할 수 있습니다. 약간의 해결 방법이지만 아무것도 아닌 것보다 낫습니다.

실제로 JDK 1.5+에서는 최대 절전 모드가 최종 필드 변경을 (리플렉션을 통해) 처리할 수 있습니다.필드를 일부 기본값/null 등으로 설정하는 보호된 기본 생성자()를 만듭니다.Hibernate는 객체를 인스턴스화할 때 이러한 값을 재정의할 수 있고 재정의할 것입니다.

이는 모두 직렬화/역직렬화를 가능하게 하기 위해 만들어진 Java 1.5 메모리 모델의 변경 사항(최종값이 최종적이지 않도록 허용) 덕분에 가능합니다.

public class Event {

private final Long id;
private final String title;
private final Date date;

// Purely for serialization/deserialization
protected Event() {
    id = null;
    title = null;
    date = null;
}

public Event(Long id, String title, Data date) {
    this.id = id;
    this.title = title;
    this.date = date;
}

/* Accessor methods... */

}

이것은 오랫동안 나를 괴롭 혔습니다. 내가 최근에 시도한 한 가지 아이디어는 이것입니다 - 모델 클래스의 읽기 전용 인터페이스를 정의하고 DAO와 공장이 대신 대신에 반환하도록합니다. 즉, 구현이 변수가 변하지 않더라도 DAO/Factory 객체를 남겨두면 더 이상 조정할 수 없습니다.

그렇게 :

public interface Grape {
  public Color getColor();
}

public class HibernateGrapeDao {
  public Grape findGrape(int grapeId) {
    HibernateGrape grape = hibernate.find(...
    return grape;
  }
}

class HibernateGrape implements Grape {
 ....
}

구현 클래스 패키지-프라이버시를 DAO 패키지로 유지하기를 원할 수도 있으므로 아무도 직접적으로 바이올린을 할 수 없습니다. 조금 더 많은 작업이지만 아마도 장기적으로 물건을 깨끗하게 유지하는 데 도움이됩니다. 그리고 분명히 전체 평등/정체성 사업에주의하십시오.

빌더 패턴을 사용하여 원하는 결과를 달성 할 수 있습니다. 나는 a를 읽었다 전기 얼마 전 최대 절전 모드 포럼에서 아이디어를 논의하는 (나는 직접 구현하지는 않았지만 ...)

@Access (accessType.field)로 수업을 주석에 넣으면 필드를 최종적으로 만들 수 있습니다. 이와 같이:

@Access(AccessType.FIELD)
public final class Event {

    private final Long id;
    private final String title;
    private final Date date;

    private Event() {
        id = null;
        title = null;
        date = null;
    }

    public Event(Long id, String title, Date date) {
        this.id = id;
        this.title = title;
        this.date = date;
    }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top