Hibernate кэш 2-го уровня только пишет, но не читает - PullRequest
3 голосов
/ 11 ноября 2011

У меня есть следующие две сущности

лицо:

@Entity
@Table(name = "person")
public class PersonDTO implements Serializable {

    private static final long serialVersionUID = -3859029259805663330L;

    @Id
    @Column(name = "person_id")
    @SequenceGenerator(name = "PERSON_GENERATOR", sequenceName = "seq_person_id")
    @GeneratedValue(generator = "PERSON_GENERATOR")
    private Long personId;

    @Column(name = "name")
    private String name;

    @OneToMany(fetch = FetchType.LAZY)
    @JoinColumn(name = "person_id", updatable = false)
    @Cascade(value = { CascadeType.ALL, CascadeType.DELETE_ORPHAN })
    private List<PersonBookDTO> personBooks = new ArrayList<PersonBookDTO>();

    public Long getPersonId() {
    return personId;
    }

    public void setPersonId(final Long personId) {
    this.personId = personId;
    }

    public String getName() {
    return name;
    }

    public void setName(final String name) {
    this.name = name;
    }

    public List<PersonBookDTO> getPersonBooks() {
    return personBooks;
    }

    public void setPersonBooks(final List<PersonBookDTO> personBooks) {
    this.personBooks = personBooks;
    }

    /**
     * @see java.lang.Object#equals(Object)
     */
    @Override
    public boolean equals(final Object object) {
    if (!(object instanceof PersonDTO)) {
        return false;
    }
    PersonDTO rhs = (PersonDTO) object;
    return new EqualsBuilder().appendSuper(super.equals(object))
        .append(this.name, rhs.name).isEquals();
    }

    /**
     * @see java.lang.Object#hashCode()
     */
    @Override
    public int hashCode() {
    return new HashCodeBuilder(1636021877, -141724713)
        .appendSuper(super.hashCode())
        .append(this.name).toHashCode();
    }
}

Персональная книга:

@Entity
@Table(name = "person_book")
@NamedQueries({
    @NamedQuery(name = "PersonBookDTO.getBooksByPersonIdList", query = "from PersonBookDTO s where s.person.personId in(:personIdList) and s.disabled=false")
})
public class PersonBookDTO implements Serializable {
    private static final long serialVersionUID = -6382678873261874993L;

    @Id
    @Column(name = "person_book_id")
    @SequenceGenerator(name = "PERSON_BOOK_GENERATOR", sequenceName = "seq_person_book_id")
    @GeneratedValue(generator = "PERSON_BOOK_GENERATOR")
    private Long personBookId;

    @Column(name = "name")
    private String name;

    @Column(name = "disabled")
    private boolean disabled;

    @ManyToOne()
    @JoinColumn(name = "person_id")
    private PersonDTO person;

    public Long getPersonBookId() {
        return personBookId;
    }

    public void setPersonBookId(Long personBookId) {
        this.personBookId = personBookId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public boolean isDisabled() {
        return disabled;
    }

    public void setDisabled(boolean disabled) {
        this.disabled = disabled;
    }

    public PersonDTO getPerson() {
        return person;
    }

    public void setPerson(PersonDTO person) {
        this.person = person;
    }

    /**
     * @see java.lang.Object#equals(Object)
     */
    public boolean equals(Object object) {
        if (!(object instanceof PersonBookDTO)) {
            return false;
        }
        PersonBookDTO rhs = (PersonBookDTO) object;
        return new EqualsBuilder().appendSuper(super.equals(object)).append(this.disabled, rhs.disabled).append(this.personBookId, rhs.personBookId).append(this.name, rhs.name).append(this.person, rhs.person).isEquals();
    }

    /**
     * @see java.lang.Object#hashCode()
     */
    public int hashCode() {
        return new HashCodeBuilder(213186089, -1592457573).appendSuper(super.hashCode()).append(this.disabled).append(this.personBookId).append(this.name).append(this.person).toHashCode();
    }
}

Я включил hibernate кэш 2-го уровня для этих объектов:

<property name="hibernate.cache.use_second_level_cache">true</property>
<property name="hibernate.cache.provider_class">net.sf.ehcache.hibernate.EhCacheProvider</property>
<property name="net.sf.ehcache.configurationResourceName">/ehcache.xml</property>
...
<class-cache usage="read-write" class="com.test.dao.dto.PersonDTO"/>
<class-cache usage="read-write" class="com.test.dao.dto.PersonBookDTO"/>

Кэш по умолчанию из ehcache.xml:

<defaultCache 
    maxElementsInMemory="100000" 
    eternal="false"
    timeToIdleSeconds="86400" 
    timeToLiveSeconds="86400" 
    overflowToDisk="false"
    memoryStoreEvictionPolicy="LRU" 
    statistics="false"
>

Теперь я вызываю следующий тестовый метод в цикле несколько раз и в нескольких потоках: (personIdList является списком и был заполнен ранее)

txManager.startTransaction();
Query query = getSession().getNamedQuery("PersonBookDTO.getBooksByPersonIdList");
query.setParameterList("personIdList", personIdList);
List<PersonBookDTO> =  query.list();
txManager.commitTransaction();
txManager.closeTransaction();

Когда я собирал статистику кэширования 2-го уровня в спящем режиме, я видел, что во время цикла из кэша извлекался только PersonDTO.

name: com.test.dao.dto.PersonDTO
count: 13
hit: 4
miss: 4
put: 13
size: 35389

и PersonBookDTO было написано только

name: com.test.dao.dto.PersonBookDTO 
count: 29
hit: 0
miss: 0
put: 29
size: 38194

Я включил уровень TRACE для ehCache. Вот часть журнала:

TRACE [ReadWriteCache] Caching: com.test.dao.dto.PersonBookDTO#8348946
TRACE [ReadWriteCache] Cached: com.test.dao.dto.PersonBookDTO#8348946
TRACE [ReadWriteCache] Cache hit: com.test.dao.dto.PersonDTO#70276
TRACE [ReadWriteCache] Cache hit: com.test.dao.dto.PersonDTO#79271
TRACE [ReadWriteCache] Caching: com.test.dao.dto.PersonBookDTO#8376615
TRACE [ReadWriteCache] Item was already cached: com.test.dao.dto.PersonBookDTO#8376615
TRACE [ReadWriteCache] Cache hit: com.test.dao.dto.PersonDTO#63179
TRACE [ReadWriteCache] Caching: com.test.dao.dto.PersonBookDTO#8315141
TRACE [ReadWriteCache] Item was already cached: com.test.dao.dto.PersonBookDTO#8315141

Может быть, кто-то может объяснить это поведение. Спасибо!

ОБНОВЛЕНИЕ: воспроизводится со всеми запросами, которые возвращают списки DTO. session.read (PersonBookDTO) читает из кэша нормально.

1 Ответ

0 голосов
/ 11 ноября 2011

Результаты явного запроса извлекаются из кэша второго уровня, только если кэш запроса включен и включен для этого запроса (путем установки соответствующих подсказок запроса).Итак, если вы хотите кэшировать результаты запроса, вам нужно включить кеш запросов.

Если вы хотите получить данные сущности из кэша второго уровня, но не хотите получать результат запроса в целомиз кеша запросов вы можете запустить запрос для идентификаторов, а затем вручную извлечь объекты с этими идентификаторами.

...