최대 절전 모드를 사용하여 세션이 닫힌 후 지연 로드된 필드에 어떻게 액세스할 수 있나요?

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

  •  21-08-2019
  •  | 
  •  

문제

다음 시나리오를 고려하십시오.

  • 최대 절전 모드를 통해 상위 엔터티를 로드했습니다.
  • 상위에는 크고 지연 로드되는 하위 컬렉션이 포함되어 있습니다.
  • 사용자가 상위 데이터를 보는 동안 이 초기 로드 후 최대 절전 모드 세션이 닫힙니다.
  • 사용자는 게으른 어린이 컬렉션의 내용을 보도록 선택할 수 있습니다.
  • 이제 해당 컬렉션을 로드하고 싶습니다.

이 컬렉션을 로드하는 방법/가장 좋은 방법은 무엇입니까?

  • Children 컬렉션 가져오기는 사용자가 Parent를 보고 Children을 보기로 결정한 후에만 발생하므로 session-in-view는 옵션이 아니라고 가정합니다.
  • 이는 웹 및 데스크톱 기반 클라이언트에서 원격으로 액세스할 수 있는 서비스입니다.

감사해요.

도움이 되었습니까?

해결책

사용자가 보고 있는 내용에 대해 몇 가지 가정을 하고 있지만 사용자가 이미 부모를 보았고 실제로 자식을 보고 싶어하는 경우에만 자식을 검색하려는 것 같습니다.

새로운 세션을 열고 부모가 아이들을 불러오는 것은 어떨까요?뭔가...

criteria = session.createCriteria(Child.class);
criteria.add(Restrictions.eq("parent", parent));
List<Child> children = criteria.list();

다른 팁

게으른 컬렉션은 상위 객체가 활성 세션에 연결되어야 한다는 점을 제외하고는 Hibernate.initialize(parent.getCollection())을 사용하여 로드될 수 있습니다.

이 솔루션은 상위 엔터티와 지연 로드 필드의 이름을 사용하고 컬렉션이 완전히 로드된 엔터티를 반환합니다.

안타깝게도 상위 항목을 새로 열린 세션에 다시 연결해야 하기 때문에 게으른 컬렉션에 대한 참조를 사용할 수 없습니다. 이는 분리된 엔터티 버전을 참조하기 때문입니다.따라서 fieldName과 반사입니다.같은 이유로 연결된 상위 엔터티를 반환해야 합니다.

따라서 OP 시나리오에서는 사용자가 게으른 컬렉션을 보도록 선택할 때 이 호출이 이루어질 수 있습니다.

Parent parentWithChildren = dao.initialize(parent,"lazyCollectionName");

방법:

public Entity initialize(Entity detachedParent,String fieldName) {
    // ...open a hibernate session...
    // reattaches parent to session
    Entity reattachedParent = (Entity) session.merge(detachedParent); 

    // get the field from the entity and initialize it
    Field fieldToInitialize = detachedParent.getClass().getDeclaredField(fieldName);
    fieldToInitialize.setAccessible(true);
    Object objectToInitialize = fieldToInitialize.get(reattachedParent);

    Hibernate.initialize(objectToInitialize);
    return reattachedParent;
}

Hibernate는 일반 필드와 다른 방식으로 컬렉션을 처리합니다.

내 작업에서는 사례별로 필요한 초기 로드의 필드를 초기화하여 이 문제를 해결합니다.예를 들어, 트랜잭션으로 둘러싸인 Facade 로드 메소드에는 다음이 있을 수 있습니다.

public Parent loadParentWithIntent1(Long parentId)
{
  Parent parent = loadParentFromDAO();

  for (Child c : parent.getChildren())
  {
    c.getField1();
  }
}

각 인텐트에 대해 서로 다른 Facade 호출이 있습니다.어떤 식으로든 필요할 때 이러한 특정 필드를 로드하고 로드 시 세션에 넣기 때문에 이는 본질적으로 필요한 것을 달성합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top