我有接下来的两个实体
人:
@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是一个列表,之前已填充)
txManager.startTransaction();
Query query = getSession().getNamedQuery("PersonBookDTO.getBooksByPersonIdList");
query.setParameterList("personIdList", personIdList);
List<PersonBookDTO> = query.list();
txManager.commitTransaction();
txManager.closeTransaction();
当我收集hibernate二级缓存statistis时,我发现在循环期间只有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
也许有人可以解释这个行为。谢谢!
UPDATE:会重现所有返回DTO列表的查询。 session.read(PersonBookDTO)正常从缓存中读取。
答案 0 :(得分:0)
仅当为query cache打开并为该查询启用时(通过设置适当的查询提示),才从二级缓存中获取显式查询的结果。因此,如果要缓存查询结果,则需要启用查询缓存。
如果要从二级缓存中检索实体数据,但不希望从查询缓存中检索整个查询结果,则可以运行id查询,然后手动获取具有这些ID的实体。 / p>