내 POJO (카테고리)는 langMap
(언어 맵)이며 Locale -> String
매핑을 저장합니다. 내가지도를 업데이트 할 때까지 그것은 잘 작동JPA @ ElementCollection이 신비하게 캐시 됨
@Entity
class Category implements Serializable {
@ElementCollection
@MapKeyColumn(name = "locale")
@Column(name = "name")
@CollectionTable(name = "CategoryName", joinColumns = @JoinColumn(name = "category_id"))
private Map<Locale, String> langMap = new HashMap<>();
// other fields skipped.
}
:이 정의되어 코드는 간단하다 :
public void replaceLangMap(Map<Locale, String> map) {
langMap.clear();
langMap.putAll(map);
}
지우기 모든 langMap
넣어 새 값. (물론, @Transactional
merged())
그러나보기 레이어를 새로 고침 할 때 이전 맵의 결과가 표시되는 경우가 있습니다. 캐싱 레이어를 추가하지 않을 것이라고 확신합니다. 여기
제가보고 정의 : 예
, 올바르게 도시되어있는 MySQL
en -> Vocation
de_DE -> Berufung
저장 한 종류가있다 :
mysql> select * from CategoryName where category_id = 1;
+-------------+----------+--------+
| category_id | name | locale |
+-------------+----------+--------+
| 1 | Berufung | de_DE |
| 1 | Vocation | en |
+-------------+----------+--------+
2 rows in set (0.00 sec)
하고 뷰 층
, 각 이름에 의도적으로 "X"를 추가했습니다.투입 후에는 제대로 된지도를 교체하고 MySQL의의 값은 정말 수정 :
mysql> select * from CategoryName where category_id = 1;
+-------------+-----------+--------+
| category_id | name | locale |
+-------------+-----------+--------+
| 1 | BerufungX | de_DE |
| 1 | VocationX | en |
+-------------+-----------+--------+
2 rows in set (0.00 sec)
을하지만 같은 페이지를 다시로드 할 때, 나는 가끔 (도시 고지도를 볼 수 없습니다 항상 50/50)
18:14:42.698 INFO models.Category - en -> VocationX
18:14:42.698 INFO models.Category - de_DE -> BerufungX
18:14:42.706 INFO models.Category - en -> VocationX
18:14:42.706 INFO models.Category - de_DE -> BerufungX
18:14:44.165 INFO models.Category - en -> Vocation
18:14:44.165 INFO models.Category - de_DE -> Berufung
로그가 아닌 뷰 층 도메인 오브젝트 (Category
)에 기록된다. 모든 새로 고침은 POJO에서 로그를 트리거합니다. 따라서 뷰 레이어가 아무 것도 캐시하지 않는다고 확신합니다.
메모리에서이 제거되지 않고, 최대 절전 모드가 때때로 해당 버전을 얻는 것 같습니다. 다시 수정하면 무작위로 회전하는지도의 3 가지 버전이 있습니다 ... 이상합니다.
서버를 다시 시작하면 항상 올바른 langMap
을 얻을 수 있습니다.
무엇이 잘못 될 수 있습니까?
환경 :
hibernate-jpa-2.1-api-1.0.0.Final
Hibernate 4.3.1.Final
MySQL 5.5.21 - MySQL Community Server
Table is innodb
mysql client library : mysql-connector-java 5.1.27
------------ 호기심에서
------------ 업데이트, 내가 찾고 싶어요 여부를 CategoryDao.get(1)
정말 안타 db. 나는 hibernate.show_sql=true
을 켜고 CategoryDao.get(1)
에 일부 로깅을 추가 한 다음 프로세스를 다시 실행합니다.
@Override
public Category get(Serializable id) {
if (id == null)
throw new PersistenceException("id may not be null");
Category obj = emp.get().find(Category.class, id);
logger.info("get id={} of object class {}", id, Category.class.getSimpleName());
return obj;
}
그리고 결과 :
select aaa as aaa , bbb as bbb , … // fields skipped
from
Category category0_
left outer join
CategoryName langmap1_
on category0_.id=langmap1_.category_id
where
category0_.id=?
INFO d.CategoryDao$$EnhancerByGuice$$1904dfdf - get id=1 of object class Category
INFO d.CategoryDao$$EnhancerByGuice$$1904dfdf - get id=1 of object class Category
INFO d.CategoryDao$$EnhancerByGuice$$1904dfdf - get id=1 of object class Category
이 모든 get()
예상 될 것이었다으로, 이전 데이터는 SQL 로그를 표시되지 않는, 로거를 트리거하지만. 그들은 DB를 치지 않는 것 같습니다. 때로는 최신 데이터가 SQL 로그를 표시하지 않습니다. 어쨌든 SQL 코드를 보여 주면 그 결과는 확실히 최신입니다.
이것은 캐시 문제로 보입니다. 하지만 여기에 ehcahce를 포함하여 어떤 캐시도 사용하지 않습니다. 심지어 hibernate.cache.use_query_cache
및 hibernate.cache.use_second_level_cache
을 false로 설정했지만 헛수고입니다.
무엇이 잘못 될 수 있습니까?
은 ------------ 주석에서 업데이트 2 ------------
, 나는 내가 DAO의 get(id)
에 @Transactional
을 도입하여 문제를 해결할 생각했다 방법. 그러나 전체 (웹) 액션이 카테고리를 검색 할 때만 작동합니다. 그것은 아무리 내가 수정하는 방법, 잘 작동하지
public Result category(@Param("id") Long id) {
Category category = categoryDao.get(id);
return Results.html()
.render("category" , category);
}
범주의 langMap
의 langMap
가 제대로 DB에 저장하고 DB에서 검색한다 : 예를 들어, 다음은 OK입니다. 나는 SQL을보고, 모든 get(id)
은 실제로 DB를 쳤다.
그러나 실제로이 작업은 일반적으로 하나의 범주 개체를 렌더링하지 않습니다. 예를 들어, 나는 범주 아래에 다른 subCategories
를 가져 오는 쿼리, 또는 항목이 있습니다
Category category = categoryDao.get(id);
Map<Category , Long> catMap = categoryDao.getSubCategories(category).stream()
.collect(Collectors.toMap(cat -> cat, cat -> categoryDao.getChildCount(cat)));
List<DataDto> dataList = dataService.getDataList(category , page , count);
이러한 조치는, OK 보인다 오프라인 테스트도 OK입니다. 그러나 온라인에서 카테고리의 langMap
을 업데이트 한 후 신비하게 캐시 된 langMap
은 때때로 다시 뜨다 (WTF!). 그리고 categoryDao.get(id)
이 항상 DB를 치는 것은 아닙니다.
글쎄, 여기에 무슨 문제가있을 수 있습니까?
, 나는 Transactional' @ 내 DAO의'공공 부문 얻을 (직렬화 ID)', 그리고 이상한 행동에'추가 : 여기
몇 가지 링크입니다 사라졌습니다 ... 나는 여전히 이상하게 느껴집니다 ... 왜 읽는 것이 거래가되어야합니까 ... – smallufo죄송합니다, 이전 코멘트를 철회해야합니다. 'Update 2'를보십시오. – smallufo
신비한 캐싱을 제거하는 유일한 방법은 모든 DAO의 메소드'@ Transactional'을 표시하는 것입니다 (또는 DAO 클래스'@ Transactional'을 표시하는 것입니다). 아무거나 독서 또는 다른 사람. C/U/D는 틀림없이'@ Transactional'입니다. 그러나'@ TransactionTo'를 읽는 것을 좋아하지 않습니다. 왜냐하면'@ OneToMany'를'LAZY' 페칭으로 무효화 할 것이기 때문입니다. 나는 여전히 더 나은 해결책을 찾고있다. – smallufo