hibernate二级缓存使用hazelcast实现,集合元素不是从缓存中检索的,而是从数据库中检索的
我对二级缓存有一种“奇怪”的行为,它不会从缓存中命中集合的元素,而是从数据库中命中集合的元素 有三个类可以建模用户和组之间具有属性的多个关系 用户和组类从中继承的Person类:hibernate二级缓存使用hazelcast实现,集合元素不是从缓存中检索的,而是从数据库中检索的,hibernate,spring-boot,orm,hazelcast,second-level-cache,Hibernate,Spring Boot,Orm,Hazelcast,Second Level Cache,我对二级缓存有一种“奇怪”的行为,它不会从缓存中命中集合的元素,而是从数据库中命中集合的元素 有三个类可以建模用户和组之间具有属性的多个关系 用户和组类从中继承的Person类: @Entity @DiscriminatorColumn(name = "userType", discriminatorType = DiscriminatorType.INTEGER) @Inheritance(strategy = InheritanceType.SINGLE_TABLE) @Cacheable
@Entity
@DiscriminatorColumn(name = "userType", discriminatorType = DiscriminatorType.INTEGER)
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@Cacheable
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Person implements Serializable {
...
}
@Entity
@DiscriminatorValue("2")
public class User extends Person {
@OneToMany(mappedBy = "user", cascade = {CascadeType.ALL}, orphanRemoval = true, fetch = FetchType.LAZY)
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
protected Set<UserGroup> userGroups = new HashSet<>();
}
@Entity
@DiscriminatorValue("2")
public class Group extends Person {
@OneToMany(mappedBy = "group", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
protected Set<UserGroup> users = new HashSet<>();
}
所有实体和集合都配置为可缓存
我做了一个测试,在这个测试中,我从数据库中的一个用户的ID中检索了一个用户,然后我对UserGroup集合进行了一次get,hibernate生成了这个查询,这是因为惰性模式配置的缘故。
我在一个循环中做了好几次
@Test
@Transactional
public void level2QueryCacheSelectTest() {
for (int i = 0; i < 5; i++) {
Optional<User> oUser = this.userRepository.findById(1l);
User user = oUser.get();
logger.info(user.toString());
for (UserGroup ug : user.getUserGroups()) {
logger.info(ug.toString());
}
}
}
仅使用用户id检索的用户组,即user.userGroups集合的元素
select
usergroups0_.id_user as id_user2_6_0_,
usergroups0_.id_group as id_group1_6_0_,
...
from
user_group usergroups0_
where
usergroups0_.id_user=?
这里是我可以通过Hazelcast mancenter看到的二级缓存中的结果
用户是4个组的成员,因此在oauth2.domain.UserGroup区域中有4个条目,在oauth2.domain.userGroups区域中有1个集合
现在是第二次执行出现问题的测试:)
在测试的第一次迭代中,Hibernate使用用户id和组id对UserGroup表进行4次查询。因此,他可以在缓存中检索集合(因为他已经知道组的id),但不能检索应该位于oauth2.domain.UserGroup区域中的集合元素
select
usergroup0_.id_group as id_group1_6_0_,
usergroup0_.id_user as id_user2_6_0_,
from
user_group usergroup0_
where
usergroup0_.id_group=?
and usergroup0_.id_user=?
binding parameter [1] as [BIGINT] - [9]
binding parameter [2] as [BIGINT] - [1]
其他3个用户组也一样
现在缓存中有8个UserGroup元素
我不知道为什么在缓存中找不到元素,我使用嵌入的ID实现了用户组类的hashcode和equals。但是我不确定Hazelcast是如何完成这项工作的,所以可能存在配置错误。如果你知道我如何解决这个问题,欢迎你
版本:
冬眠:5.3.12.1决赛
Hazelcast-hibernate53:1.3.2
Hazelcast:3.12.3
弹簧靴:2.0.0.0版本
这是Hazelcast和jpa的Spring引导配置
spring:
datasource:
jdbc-url: jdbc:mysql://mysql-server:3306/oauth2
username: ********
password: ********
initialization-mode: never
jpa:
hibernate:
ddl-auto: update
properties:
hibernate:
cache:
#required - turn on L2 cache.
use_second_level_cache: true
#optional - turn on query cache.
use_query_cache: true
hazelcast:
use_native_client: true
native_client_address: hazelcast-member:5701
native_client_group: *********
native_client_password: *********
region:
factory_class: com.hazelcast.hibernate.HazelcastCacheRegionFactory
format_sql: true
#optional - generate statistics to check if L2/query cache is actually being used.
generate_statistics: true
你能显示你的
application.properties | yml
文件吗?@Cepr0当然我加了Hazelcast和jpastange的配置。。。设置似乎是正确的。问题可能出在复杂的实体模式中。或者,原因可能是您在UserGroup
中实现的hashCode
不完全正确-当您为“-toMany”关联使用Set
时,最好使用这个。看看我的-我希望它会有用。我使用的测试方法是junit测试。它抛出了一个LazyInitializationException,所以我在方法级别添加了一个@Transactional注释以使其正常工作。这就是问题的根源,我在我的应用程序中进行了实时测试,在没有注释的情况下,它可以正常工作。在我的集合中,我从不添加任何ID为null的元素,因此我认为这不是问题,我不同意hashcode总是返回相同值的技巧,因为该值用于快速检索、删除或添加元素。(~O(1))。感谢回购协议,我会看一看;)
select
usergroups0_.id_user as id_user2_6_0_,
usergroups0_.id_group as id_group1_6_0_,
...
from
user_group usergroups0_
where
usergroups0_.id_user=?
select
usergroup0_.id_group as id_group1_6_0_,
usergroup0_.id_user as id_user2_6_0_,
from
user_group usergroup0_
where
usergroup0_.id_group=?
and usergroup0_.id_user=?
binding parameter [1] as [BIGINT] - [9]
binding parameter [2] as [BIGINT] - [1]
spring:
datasource:
jdbc-url: jdbc:mysql://mysql-server:3306/oauth2
username: ********
password: ********
initialization-mode: never
jpa:
hibernate:
ddl-auto: update
properties:
hibernate:
cache:
#required - turn on L2 cache.
use_second_level_cache: true
#optional - turn on query cache.
use_query_cache: true
hazelcast:
use_native_client: true
native_client_address: hazelcast-member:5701
native_client_group: *********
native_client_password: *********
region:
factory_class: com.hazelcast.hibernate.HazelcastCacheRegionFactory
format_sql: true
#optional - generate statistics to check if L2/query cache is actually being used.
generate_statistics: true