문제

빠른 버전

기본적으로 나는 Hibernate 테이블을 업데이트하고 있으며 후속 쿼리는 오래된 값을 로드하고 있습니다.

상세 버전

최대 절전 모드(3.3.1.GA) 및 EhCache(2.4.2).

지속됨 Book 을 가진 객체 List<PageContent> 페이지 수가 많아서 이 책 중간에 페이지를 추가하겠습니다.저는 Databinder/Wicket을 사용하고 있지만 관련이 없다고 생각합니다.

 public void createPageContent(Book book, int index) {
     Databinder.getHibernateSession().lock(book, LockMode.UPGRADE);
     PageContent page = new PageContent(book);
     book.addPage(page, index);
     CwmService.get().flushChanges(); // commits the transaction
 }

해당 필드/방법은 Book 이다:

@OneToMany
@JoinColumn(name="book_id")
@IndexColumn(name="pageNum")
@Cascade({CascadeType.ALL, CascadeType.DELETE_ORPHAN})
private List<PageContent> pages = new ArrayList<PageContent>();

public synchronized void addPage(PageContent page, int index) {
    pages.add(index, page);
}

최종 결과는 목록에 새 페이지가 추가되고 이에 따라 데이터베이스가 업데이트되는 것이며 데이터 저장소에서 이를 확인했습니다.그러나 페이지에 대한 다음 쿼리인 "페이지 #4"는 새 페이지 #4 대신 "이전" 페이지 #4를 로드합니다.

criteria.add(Restrictions.eq("book", book));
criteria.add(Restrictions.eq("pageNum", pageNum));
criteria.setCacheable(true);  

그래서 저는 마지못해 기준에서 캐싱을 제거했습니다.데이터 저장소를 쿼리하지만 여전히 잘못된 값을 반환합니다..하지만 두 경우 모두 2분 정도 기다리면 모든 것이 예상대로 작동합니다.캐싱이 여전히 관련되어 있다고 가정합니다.둘 다 PageContent 그리고 Book 다음 캐싱 전략을 사용하세요.

@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)

나는 캐싱을 처음 접했고 처음으로 이 파일을 설정했다고 고백합니다.내 ehcache.xml은 다음과 같습니다.

<defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" diskSpoolBufferSizeMB="30" maxElementsOnDisk="10000000" diskPersistent="false" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU" statistics="false"/>

<!-- Hibernate's Cache for keeping 'lastUpdated' data on each table.  Should never expire. -->
<cache name="org.hibernate.cache.UpdateTimestampsCache" eternal="true" />

<!-- Hibernate's Query Cache - should probably be limited -->
<cache name="org.hibernate.cache.StandardQueryCache" maxElementsInMemory="1000" />

업데이트:제거 @Cache 내 데이터 저장소 개체에 주석을 추가하면 문제가 제거됩니다.물론 페이지 수정은 액세스보다 훨씬 덜 빈번하기 때문에 이러한 개체를 캐시하고 싶습니다.

그럼 생각은?페이지 삭제를 포함하여 관련된 몇 가지 다른 문제도 있습니다.모든 것이 예상대로 데이터베이스를 업데이트하지만 실제 동작은 불안정합니다.

미리 감사드립니다!

업데이트 #2:디버깅을 통해 데이터 저장소에 올바른 정보가 있는지 확인할 수 있으며 쿼리가 실행되면 더티 정보가 있는 두 번째 수준 캐시로 대체됩니다.데이터가 변경될 때마다 캐시에서 제거하는 것이 나에게 달려 있지 않다고 생각합니까?

도움이 되었습니까?

해결책 2

문제를 발견했지만 다른 문제가 발생했습니다.

기본적으로 수정시에는 Book 사물 List<PageContent> 필드에서 Hibernate는 세 가지 일을 합니다:

  1. 두 가지 모두에 대한 TimeStamp 캐시 항목을 만료합니다. Book 그리고 PageContent
  2. 재설정하기 위해 많은 쿼리를 수행합니까? pageNum 각각의 필드 PageContent 물체
  3. 제거합니다 Book 두 번째 수준 캐시의 개체입니다.

이렇게 하면 후속 쿼리에서 새 객체 등을 검색하게 됩니다.하지만:

  1. Hibernate가 번호가 다시 매겨진 각각을 제거하지 못합니다. PageContent 두 번째 수준 캐시의 개체

결과적으로 페이지 목록에 대한 모든 쿼리는 제대로 실행되지만 실제 데이터에 대해서는 오래된 두 번째 수준 캐시 값을 사용하게 됩니다.

나는 이것이 Hibernate가 다음과 같은 느낌을 받기 때문이라고 추측합니다. pageNum 변화는 데이터의 변화가 아니라 이면 관리의 변화입니다.그러나 그것은 내가 읽고 표시하고 싶은 데이터입니다.

해결 방법은 삽입/삭제가 발생한 후 모든 페이지를 수동으로 새로 고치는 것입니다.

다른 팁

후에 CwmService.get().flushChanges(); // commits the transaction 명시적인 커밋을 수행합니다.flush() 변경 사항을 db에 플러시하기만 하고 커밋하지는 않습니다.잘 모르겠습니다 flushChanges() 그렇지만.

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