2017-03-06 9 views
3

하이버 네이트 5.2.5를 사용하고 (kotlin과 spring 4.3.5가 중요하다면) 나는 클래스의 필드 일부를 느리게로드하기를 원한다. 하지만 문제는 모든 필드가 즉시 로딩된다는 것입니다. Hibernate.initialize()를 사용하지 않는 특별한 Hibernate 설정이 없습니다.Hibernate는 'lazy'페치 타입을 무시하고 즉시 프로퍼티들을로드한다.

@Entity(name = "task") 
@Table(name = "tasks") 
@NamedQueries(
     NamedQuery(name = "task.findById", query = "SELECT t FROM task AS t WHERE t.id = :id") 
) 
class Task { 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    var id: Int? = null 

    @ManyToOne(fetch = FetchType.LAZY) 
    @JoinColumn(name = "author_id", nullable = false) 
    lateinit var author: User 

    @OneToOne(fetch = FetchType.LAZY, mappedBy = "task") 
    var edit: TaskEdit? = null 
} 

이것은 내가 쿼리 방법

TaskRepoImpl입니다 :

override fun findById(id: Int): Task? { 
    val task = getCurrentSession().createNamedQuery("task.findById", Task::class.java) 
      .setParameter("id", id) 
      .uniqueResult() 
    return task 
} 

TaskService :

@Transactional 
fun find(id: Int): Task? { 
    return taskRepo.findById(id) 
} 

그리고 출력 :

Hibernate: select task0_.id as id1_1_, task0_.author_id as author_i3_1_ from tasks task0_ where task0_.id=? 
Hibernate: select user0_.id as id1_3_0_, user0_.enabled as enabled2_3_0_, user0_.name as name3_3_0_, user0_.password as password4_3_0_ from users user0_ where user0_.id=? 
Hibernate: select taskedit0_.id as id1_0_0_, taskedit0_.task_id as task_id3_0_0_, taskedit0_.text as text2_0_0_ from task_edits taskedit0_ where taskedit0_.task_id=? 

코드에 무엇이 잘못된지, 그리고 Hibernate가 등록 정보를 지연로드하는 방법을 알려주십시오. 고맙습니다!

+0

[이 답변] (http://stackoverflow.com/a/36143746/4754790) 대안 때의 개요를 제공합니다 외부 엔티티가 자식 엔티티에 의해 매핑 된 테이블에있는 일대일 관계가 게으르다. –

답변

1

Hibernate는 자신의 객체를 프록시 할 수 없습니다. 이 문제에 대해 잘 알려진 솔루션은 세 가지가 있습니다. 가장 간단한 방법은 일대 다 관계를 가짜 만드는 것입니다. 이 기능은 컬렉션의 지연로드가 단일 nullable 속성의 느린 로딩보다 훨씬 쉽기 때문에 작동하지만 일반적으로 복잡한 JPQL/HQL 쿼리를 사용하면이 솔루션은 매우 불편합니다. 다른 하나는 빌드 타임 바이트 코드 계측을 사용하는 것입니다. 더 자세한 정보는 Hibernate 문서를 참조하십시오 : 19.1.7. lazy 프로퍼티 페칭 사용하기. 이 경우 게으르도록 @LazyToOne (LazyToOneOption.NO_PROXY) 주석을 일대일 관계에 추가해야한다는 것을 기억하십시오. fetch를 LAZY로 설정하는 것만으로는 충분하지 않습니다. 마지막 해결책은 런타임 바이트 코드 계측을 사용하는 것입니다 만, 본격적인 JEE 환경에서 JPA 프로 바이더로서 Hibernate를 사용하는 사람들에게만 동작합니다 (이 경우 "hibernate.ejb.use_class_enhancer"를 true로 설정하면 트릭을 수행해야합니다 : Entity Manager Configuration)을 사용하거나 런타임 위빙을하기 위해 구성된 Spring과 함께 Hibernate를 사용하십시오 (이것은 일부 구형 어플리케이션 서버에서는 달성하기 어려울 수 있습니다). 이 경우 @LazyToOne (LazyToOneOption.NO_PROXY) 주석도 필요합니다.

@Entity 
public class Animal implements FieldHandled { 
private Person owner; 
private FieldHandler fieldHandler; 

@OneToOne(fetch = FetchType.LAZY, optional = true, mappedBy = "animal") 
@LazyToOne(LazyToOneOption.NO_PROXY) 
public Person getOwner() { 
    if (fieldHandler != null) { 
    return (Person) fieldHandler.readObject(this, "owner", owner); 
    } 
    return owner; 
} 

public void setOwner(Person owner) { 
    if (fieldHandler != null) { 
    this.owner = fieldHandler.writeObject(this, "owner", this.owner, owner); 
    return; 
    } 
    this.owner = owner; 
} 

public FieldHandler getFieldHandler() { 
    return fieldHandler; 
} 

public void setFieldHandler(FieldHandler fieldHandler) { 
    this.fieldHandler = fieldHandler; 
} 
} 

이 시도 할 수 : http://justonjava.blogspot.in/2010/09/lazy-one-to-one-and-one-to-many.html

참조 : 이 Why Lazy loading not working in one to one association?

+0

첫 번째 문제는 메소드가'open'이 아니기 때문에 Hibernate가 프록시를 생성 할 수 없었던 이유입니다. 두 번째 문제는 당신이 말했듯이 일대일 매핑이었습니다. 그것이 왜 그렇게 좋은지 여기에 있습니다 : http://stackoverflow.com/questions/1444227/making-a-onetoone-relation-lazy – awfun

+0

답변에있는 출처의 중요한 부분을 인용하십시오. –