일대일 최대 수용 모드 : 전체 객체를 가져 오지 않고 getId ()
전체 개체를로드하지 않고 일대일 관계의 ID를 가져오고 싶습니다. 다음과 같이 지연 로딩을 사용하여 할 수 있습니다.
class Foo {
@OneToOne(fetch = FetchType.LAZY, optional = false)
private Bar bar;
}
Foo f = session.get(Foo.class, fooId); // Hibernate fetches Foo
f.getBar(); // Hibernate fetches full Bar object
f.getBar().getId(); // No further fetch, returns id
f.getBar ()가 다른 가져 오기 오기를 트리거 하지 않습니다 . 최대 모드에서 실제로 Bar 개체를 가져 오지 않고 .getId ()를 호출 할 수있는 프록시 개체를 제공하고 싶습니다.
내가 도대체 뭘 잘못하고있는 겁니까?
사용 속성 액세스 전략
대신에
@OneToOne(fetch=FetchType.LAZY, optional=false)
private Bar bar;
사용하다
private Bar bar;
@OneToOne(fetch=FetchType.LAZY, optional=false)
public Bar getBar() {
return this.bar;
}
이제 잘 작동합니다!
식별자 getter 메서드가 아닌 메서드 를 호출하면 프록시가 초기화 됩니다. 그러나 속성 액세스 전략을 사용할 때만 작동합니다. 명심 해.
Arthur Ronald FD Garcia의 게시물에 추가하기 만하면됩니다. @Access(AccessType.PROPERTY)
(또는 더 이상 사용하지 않는 ) 속성 액세스를 강제 할 수 있습니다. http://256stuff.com/gray/docs/misc/hibernate_lazy_field_access_annotations.shtml을 참조하십시오.@AccessType("property")
또 다른 해결책은 다음과 가변합니다.
public static Integer getIdDirect(Entity entity) {
if (entity instanceof HibernateProxy) {
LazyInitializer lazyInitializer = ((HibernateProxy) entity).getHibernateLazyInitializer();
if (lazyInitializer.isUninitialized()) {
return (Integer) lazyInitializer.getIdentifier();
}
}
return entity.getId();
}
분리 된 배터리 작동합니다.
불행히도 허용되는 대답은 잘못되었습니다. 또한 다른 답변은 가장 명확한 솔루션을 제공하지 않습니다.
에 대한 속성 액세스 수준을 사용 ID
의 BAR
클래스입니다.
@Entity
public class Bar {
@Id
@Access(AccessType.PROPERTY)
private Long id;
...
}
그렇게 간단합니다 :)
@AccessType ( "속성") 추가
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@AccessType("property")
protected Long id;
Hibernate Book이있는 Java Persistence는 "13.1.3 Understanding Proxies"에서 참조합니다.
데이터베이스 식별자 속성에만 액세스하는 한 프록시를 초기화 할 필요가 없습니다. (직접 필드 액세스로 식별자 속성을 매핑하는 경우 이것은 사실이 아닙니다. Hibernate는 getId () 메서드가 존재하는지조차 알지 못합니다. 호출하면 프록시를 초기화해야합니다.)
그러나이 페이지의 @xmedeko 답변을 기반으로 직접 필드 액세스 전략을 사용할 때에도 프록시를 초기화하지 않도록 해킹을 개발했습니다 . getId()
아래와 같이 방법을 변경하십시오 .
대신에:
public long getId() { return id; }
사용하다:
public final long getId() {
if (this instanceof HibernateProxy) {
return (long)((HibernateProxy)this).getHibernateLazyInitializer().getIdentifier();
}
else { return id; }
}
여기서 아이디어는 getId()
메서드를으로 표시하여 final
프록시가 재정의 할 수 없도록하는 것입니다. 그러면 메서드를 호출하면 프록시 코드를 실행할 수 없으므로 프록시를 초기화 할 수 없습니다. 메서드 자체는 인스턴스가 프록시인지 확인하고이 경우 프록시에서 ID를 반환합니다. 인스턴스가 실제 개체 인 경우 ID를 반환합니다.
org.hibernate.Session에는 엔터티를 지연로드하지 않고 작업을 수행하는 함수가 있습니다.
public Serializable getIdentifier (Object object)는 HibernateException을 던집니다.
최대 절전 모드 3.3.2.GA에서 발견 :
public Serializable getIdentifier(Object object) throws HibernateException {
errorIfClosed();
checkTransactionSynchStatus();
if ( object instanceof HibernateProxy ) {
LazyInitializer li = ( (HibernateProxy) object ).getHibernateLazyInitializer();
if ( li.getSession() != this ) {
throw new TransientObjectException( "The proxy was not associated with this session" );
}
return li.getIdentifier();
}
else {
EntityEntry entry = persistenceContext.getEntry(object);
if ( entry == null ) {
throw new TransientObjectException( "The instance was not associated with this session" );
}
return entry.getId();
}
}
이제 여기에 jackson hibernate 데이터 유형 라이브러리가 있습니다.
https://github.com/FasterXML/jackson-datatype-hibernate
그리고 다음과 같은 기능을 구성 할 수 있습니다.
Hibernate4Module hibernate4Module = new Hibernate4Module();
hibernate4Module.configure(Hibernate4Module.Feature.SERIALIZE_IDENTIFIER_FOR_LAZY_NOT_LOADED_OBJECTS, true);
여기에는 지연로드 된 관계의 ID가 포함됩니다.
HQL 쿼리를 사용할 수 있습니다. getBar () 메서드는 데이터 바인딩 된 메서드를 호출 할 때까지 가져 오지 않는 프록시를 실제로 반환합니다. 나는 당신의 문제가 정확히 무엇인지 확실하지 않습니다. 배경을 좀 더 알려주시겠습니까?
다음과 같이 getter 메소드를 변경하십시오.
public Bar getBar() {
if (bar instanceof HibernateProxy) {
HibernateProxy hibernateProxy = (HibernateProxy) this.bar;
LazyInitializer lazyInitializer = hibernateProxy.getHibernateLazyInitializer();
if (lazyInitializer.getSession() == null)
bar = new Bar((long) lazyInitializer.getIdentifier());
}
return bar;
}
'ProgramingTip' 카테고리의 다른 글
Facebook은 브라우저 주소 표시 줄에서 페이지의 소스 URL을 어떻게 다시 작성합니까? (0) | 2020.12.05 |
---|---|
NSManagedObjectContext를 생성 한 단일 또는 큐가 소유하고 Apple이 말하는 것은 무엇을 의미합니까? (0) | 2020.12.05 |
SOAP 오류 또는 결과 개체? (0) | 2020.12.04 |
파일 열기 대화 상자를 사용하여 폴더를 선택할 수 있습니까? (0) | 2020.12.04 |
data.frame 또는 대규모 행 행 (0) | 2020.12.04 |