java - Hibernate二级缓存只写不读

标签 java hibernate caching ehcache second-level-cache

我有接下来的两个实体

人:

@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 二级缓存:

<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是一个List,之前已经填充过)

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

当我收集 hibernate 二级缓存统计信息时,我发现循环期间仅从缓存中获取了 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

我已启用 ehCache 的 TRACE 级别。这是日志的一部分:

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) 正常从缓存读取。

最佳答案

只有当query cache时才会从二级缓存中获取显式查询的结果。为该查询打开并启用(通过设置适当的查询提示)。因此,如果您想缓存查询结果,则需要启用查询缓存。

如果您想从二级缓存中检索实体数据,但不想从查询缓存中检索整个查询结果,您可以运行 ids 查询,然后手动获取具有这些 ids 的实体。

关于java - Hibernate二级缓存只写不读,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8094332/

相关文章:

java - 使用 jose4j 访问 JWT 嵌套声明

java - 如何取消拆分包/合并模块

java - 如何在 hibernate-5 中使用自定义表顺序?

java - 如何对 Criteria 查询执行多态显式查询?

asp.net - System.Web.Caching.Cache 似乎没有按时刷新?

Java - 一次分割和修剪

java - 需要从文件创建对象并将其放入数组中

java - org.springframework.orm.hibernate4.LocalSessionFactoryBean 无法转换为 org.hibernate.SessionFactory

caching - 实现缓存

java - Guava 文件缓存