我正在尝试将 ehcache 配置为 Hibernate 的二级缓存,但似乎它没有按预期工作。当我清除一级缓存 (PersistenceContext) 并尝试查找 Post 实体后,日志显示为了获取缓存数据出现了问题:
11:48:53.660 [main] DEBUG org.hibernate.SQL - select nextval ('hibernate_sequence')
11:48:53.704 [main] DEBUG org.hibernate.SQL - insert into Post (author, id) values (?, ?)
11:48:53.706 [main] TRACE org.hibernate.type.descriptor.sql.BasicBinder - binding parameter [1] as [VARCHAR] - [Author]
11:48:53.706 [main] TRACE org.hibernate.type.descriptor.sql.BasicBinder - binding parameter [2] as [BIGINT] - [1]
11:48:53.713 [main] DEBUG o.h.cache.internal.TimestampsCacheEnabledImpl - Pre-invalidating space [Post], timestamp: 6962383231848448
11:48:53.733 [main] DEBUG o.h.cache.internal.TimestampsCacheEnabledImpl - Pre-invalidating space [PostComment], timestamp: 6962383231930368
11:48:53.757 [main] DEBUG o.h.cache.internal.TimestampsCacheEnabledImpl - Invalidating space [Post], timestamp: 6962382986268672
11:48:53.757 [main] DEBUG o.h.cache.internal.TimestampsCacheEnabledImpl - Invalidating space [PostComment], timestamp: 6962382986268672
11:48:53.759 [main] INFO br.com.example.Main - 1st level cache cleared
11:48:53.764 [main] DEBUG o.h.cache.spi.support.AbstractReadWriteAccess - Getting cached data from region [`br.com.example.Post` (AccessType[read-write])] by key [br.com.example.Post#1]
11:48:53.765 [main] DEBUG o.h.cache.spi.support.AbstractReadWriteAccess - Checking readability of read-write cache item [timestamp=`6962382986190848`, version=`null`] : txTimestamp=`6962382985850880`
-----------> 11:48:53.765 [main] DEBUG o.h.cache.spi.support.AbstractReadWriteAccess - Cache hit, but item is unreadable/invalid : region = `br.com.example.Post`, key = `br.com.example.Post#1`**
11:48:53.767 [main] DEBUG org.hibernate.SQL - select post0_.id as id1_0_0_, post0_.author as author2_0_0_ from Post post0_ where post0_.id=?
11:48:53.768 [main] TRACE org.hibernate.type.descriptor.sql.BasicBinder - binding parameter [1] as [BIGINT] - [1]
11:48:53.774 [main] TRACE org.hibernate.type.descriptor.sql.BasicExtractor - extracted value ([author2_0_0_] : [VARCHAR]) - [Author]
11:48:53.777 [main] DEBUG o.h.cache.spi.support.AbstractReadWriteAccess - Caching data from load [region=`br.com.example.Post` (AccessType[read-write])] : key[br.com.example.Post#1] -> value[CacheEntry(br.com.example.Post)]
11:48:53.778 [main] DEBUG o.h.cache.spi.support.AbstractReadWriteAccess - Checking writeability of read-write cache item [timestamp=`6962382986190848`, version=`null`] : txTimestamp=`6962382985850880`, newVersion=`null`
-----------> 11:48:53.778 [main] DEBUG o.h.cache.spi.support.AbstractReadWriteAccess - Cache put-from-load [region=`AccessType[read-write]` (br.com.example.Post), key=`br.com.example.Post#1`, value=`CacheEntry(br.com.example.Post)`] failed due to being non-writable**
查看以箭头开头的行。这只是一条警告消息还是我的缓存不起作用?
我的实体:
@Entity
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Post implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
private String author;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "post", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<PostComment> comments = new HashSet<>();
public Set<PostComment> getComments() {
return comments;
}
public void addComment(PostComment comment) {
comments.add(comment);
comment.setPost(this);
}
public void removeComment(PostComment comment) {
comments.remove(comment);
comment.setPost(null);
}
public void removeComments() {
Iterator<PostComment> iterator = comments.iterator();
while (iterator.hasNext()) {
PostComment postComment = iterator.next();
postComment.setPost(null);
iterator.remove();
}
}
public void setAuthor(String author) {
this.author = author;
}
@Override
public String toString() {
return "Post{" +
"id=" + id +
", author='" + author + '\'' +
'}';
}
public Long getId() {
return this.id;
}
}
@Entity
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class PostComment implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "post_id")
private Post post;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PostComment that = (PostComment) o;
return id != null && Objects.equals(id, that.id);
}
@Override
public int hashCode() {
return 33;
}
public void setPost(Post post) {
this.post = post;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Post getPost() {
return post;
}
@Override
public String toString() {
return "PostComment{" +
"id=" + id +
'}';
}
}
持久性.xml:
<!-- caching -->
<property name="hibernate.cache.use_second_level_cache" value="true"/>
<property name="hibernate.cache.region.factory_class" value="jcache"/>
<property name="hibernate.javax.cache.provider" value="org.ehcache.jsr107.EhcacheCachingProvider"/>
<property name="hibernate.cache.use_query_cache" value="true"/>
<property name="hibernate.javax.cache.uri" value="file:src/main/resources/META-INF/ehcache.xml"/>
<property name="hibernate.javax.cache.missing_cache_strategy" value="create"/>
ehcache.xml:
<ehcache:cache-template name="myDefaultTemplate">
<ehcache:expiry>
<ehcache:none/>
</ehcache:expiry>
<!--
OPTIONAL
Any further elements in another namespace
-->
</ehcache:cache-template>
<!--
A <cache> that uses the template above by referencing the cache-template's name in the uses-template attribute:
-->
<ehcache:cache alias="cachePost" uses-template="myDefaultTemplate">
<!--
Adds the key and value type configuration
-->
<ehcache:key-type>java.lang.Long</ehcache:key-type>
<ehcache:value-type>br.com.example.Post</ehcache:value-type>
<!--
Overwrites the capacity limit set by the template to a new value
-->
<ehcache:heap unit="entries">200</ehcache:heap>
</ehcache:cache>
<ehcache:cache alias="cachePostComment" uses-template="myDefaultTemplate">
<!--
Adds the key and value type configuration
-->
<ehcache:key-type>java.lang.Long</ehcache:key-type>
<ehcache:value-type>br.com.example.PostComment</ehcache:value-type>
<!--
Overwrites the capacity limit set by the template to a new value
-->
<ehcache:heap unit="entries">200</ehcache:heap>
</ehcache:cache>
主要代码:
public static void main(String[] args) {
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("test-pu");
EntityManager entityManager = entityManagerFactory.createEntityManager();
Post post = new Post();
entityManager.getTransaction().begin();
post.setAuthor("Author");
entityManager.persist(post);
entityManager.getTransaction().commit();
entityManager.clear();
logger.info("1st level cache cleared");
Post cachedPost = entityManager.find(Post.class, post.getId());
logger.info("Post: {}", cachedPost);
entityManager.close();
entityManagerFactory.close();
}
pom.xml:
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<logback.version>1.4.7</logback.version>
<hibernate.version>5.6.15.Final</hibernate.version>
</properties>
<dependencies>
<!-- Logback Dependency to format Hibernate logs -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.6.0</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>jakarta.persistence</groupId>
<artifactId>jakarta.persistence-api</artifactId>
<version>2.2.3</version>
</dependency>
<dependency>
<groupId>javax.cache</groupId>
<artifactId>cache-api</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>3.10.6</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-jcache</artifactId>
<version>${hibernate.version}</version>
</dependency>
</dependencies>
提前致谢。
你如何解决这个问题@Eduardo Bortolatto Lopes,我没有足够的声誉来发表评论。你能帮我吗我也遇到了同样的错误并试图从过去两天解决它?