2012-02-28 2 views
0

최대 절전 모드를 사용하여 원본 웹 사이트에서 가져 오는 데이터의 로컬 캐시를 구축하려고합니다. JPA로 구성된 객체가 있고 (차이가 나는 경우) 테스트 응용 프로그램에서 읽기/쓰기가 가능합니다.최대 절전 모드를 사용하여 일반 개체 가져 오기

이제 코드를 일반 "캐싱"클래스로 이동하여 캐시에서 객체를 요청하고 정상적으로 처리 할 수있게하려고합니다. 데이터베이스에서 객체를 읽어 호출 클래스로 다시 전달할 수 있지만 객체의 콜렉션에 액세스 할 때 무서운 초기화 예외가 발생합니다. 이 원인은 무엇인지 알고 있습니다. 객체를 읽은 클래스는 데이터베이스에서 객체를 읽은 후 객체를 호출 클래스에 반환하기 전에 트랜잭션을 커밋합니다.

이 문제를 해결하기 위해 다양한 방법을 시도했으며 가장 간단한 방법은 개체를 모두 닫고 트랜잭션을 닫고 개체를 반환하기 전에 개체의 모든 컬렉션에 액세스하여 개체에 액세스하는 것입니다.

이 접근법의 문제점은 내가 데이터베이스에서 검색하고있는 객체의 구조를 알지 못한다는 것입니다. (나를 위해 Hibernate의 장점 중 하나입니다.) 따라서 적절한 메소드를로드 할 수 없습니다. 자료. 어떻게 이것을 극복 할 수 있습니까? 다른 응용 프로그램에서 사용할 수 있기 때문에 객체를 열심히 가져 오는 것을 정말로 원하지는 않습니다. 내가 그것을 피할 수 있다면 hbm 파일을 사용하고 싶지 않다. 캐시 클래스에서

Series series = (Series) Cache.getFromCache(id, Series.class) 

:

는 캐시 클래스 호출입니다

public static Object getFromCache(String key, Class clazz) { 
Object dbObject = HibernateUtil.loadObject(clazz, key); 

    if (dbObject != null) { 
     logger.debug("Cache (Get): Got object (" + clazz.getSimpleName() + ") for " + key); 
     return dbObject; 
    } 
} 

그리고 HibernateUtil과 수행합니다 모든

public static Object loadObject(Class clazz, Serializable key) { 
    Session session = sessionFactory.getCurrentSession(); 
    Object dbObject; 

    try { 
     session.beginTransaction(); 
     dbObject = clazz.cast(session.get(clazz, key)); 
    } finally { 
     session.getTransaction().commit(); 
    } 

    return dbObject; 

답변

1

먼저, 피할 수 loadObject 메서드를 매개 변수화하여 형식 캐스트 :

public static <T> T loadObject(Class<T> clazz, Serializable key) { 
    Session session = sessionFactory.getCurrentSession(); 
    T dbObject; 

    try { 
     session.beginTransaction(); 
     dbObject = clazz.cast(session.get(clazz, key)); 
    } 
    finally { 
     session.getTransaction().commit(); 
    } 

    return dbObject; 
} 

둘째 : 왜이 ​​방법으로 거래를 열고 커밋합니까? 호출자가 트랜잭션을 열고 캐시에서로드 한 객체 사용을 마쳤을 때 커밋하도록하면 문제가 해결됩니다.

셋째 :이 방법을 열고 트랜잭션을 닫으려면 매개 변수로 Initializer<T> 인스턴스를 사용하도록 설정하십시오. 이 이니셜 라이저는 엔티티를 반환하기 전에 필요한 모든 연관을 초기화 할 책임이 있습니다.

public static <T> T loadObject(Class<T> clazz, 
           Serializable key, 
           Initializer<T> initializer) { 
    Session session = sessionFactory.getCurrentSession(); 
    T dbObject; 

    try { 
     session.beginTransaction(); 
     dbObject = clazz.cast(session.get(clazz, key)); 
     initializer.initialize(dbObject); 
    } 
    finally { 
     session.getTransaction().commit(); 
    } 

    return dbObject; 
} 
+0

** 처음 : ** 감사드립니다. ** 두 번째 : ** 기존 프로젝트에 추가 된 캐시 코드 자체를 유지하려고했는데 한꺼번에 처리하지 않고 한 번에 프로젝트를 리팩터링하려고합니다. ** 셋째 : ** 내 무지를 용서해주세요.하지만 Initializer는 무엇입니까? – Omertron

+0

Initializer는 생성하고자하는 인터페이스이며, initialize (T) 메소드를 포함 할 것이며, T 객체의 연관을 loadObject 메소드에서 반환하기 전에 초기화 할 책임이 있습니다. –

+0

그래서' .getCollection(). size'를 호출하는 유틸리티 클래스 일 수 있습니까? 'initialize'가로드되는 클래스에 속해 있습니까? – Omertron

관련 문제