spring boot +hazelcast + hibernate findAll() 从数据库而不是缓存中检索数据
springboot +hazelcast + hibernate's findAll() retrive data from database not cache
我目前在我的 springboot 应用程序(版本 1.5.2.RELEASE)中使用带 hazelcast 3.7.5 的休眠二级缓存。
每当我使用由 Spring Data Jpa 实现的 findAll() 方法时,hibernate 从数据库中检索数据,但是当我使用 findOne(id) 方法时,hibernate 从 chache 获取数据。有人可以解释这种奇怪的行为吗?
这是我的休眠配置
spring:
datasource:
url: jdbc:h2:file:./target/h2db/db/parametrage;DB_CLOSE_DELAY=-1;INIT=CREATE SCHEMA IF NOT EXISTS PARAM
username: sa
password:
jpa:
open-in-view: false
show-sql: true
hibernate:
ddl-auto: none
naming:
implicit-strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
properties:
hibernate.default_schema: PARAM
hibernate.id.new_generator_mappings: true
hibernate.cache.use_second_level_cache: true
hibernate.cache.use_query_cache: false
hibernate.generate_statistics: true
hibernate.cache.region.factory_class: com.hazelcast.hibernate.HazelcastCacheRegionFactory
hibernate.cache.hazelcast.instance_name: hazelcast
hibernate.cache.use_minimal_puts: true
hibernate.cache.hazelcast.use_lite_member: true
这是我的 hazelcast 配置
@Configuration
@EnableCaching
public class CacheConfiguration {
private final Logger log = LoggerFactory.getLogger(CacheConfiguration.class);
private final Environment env;
public CacheConfiguration(Environment env) {
this.env = env;
}
@Bean
public CacheManager cacheManager(HazelcastInstance hazelcastInstance) {
log.debug("Starting HazelcastCacheManager");
CacheManager cacheManager = new HazelcastCacheManager(hazelcastInstance);
return cacheManager;
}
@PreDestroy
public void destroy() {
log.info("Closing Cache Manager");
Hazelcast.shutdownAll();
}
@Bean
public HazelcastInstance hazelcastInstance() {
log.debug("Configuring Hazelcast");
Config config = new Config();
config.setInstanceName("hazelcast");
config.getNetworkConfig().setPort(5701);
config.getNetworkConfig().setPortAutoIncrement(true);
config.getNetworkConfig().getJoin().getAwsConfig().setEnabled(false);
config.getNetworkConfig().getJoin().getMulticastConfig().setEnabled(false);
config.getNetworkConfig().getJoin().getTcpIpConfig().addMember("localhost").setEnabled(true);
config.getMapConfigs().put("default", initializeDefaultMapConfig());
config.getManagementCenterConfig().
setUrl("http://localhost:8080/mancenter")
.setEnabled(true);
return Hazelcast.newHazelcastInstance(config);
}
private MapConfig initializeDefaultMapConfig() {
MapConfig mapConfig = new MapConfig();
mapConfig.setBackupCount(0);
mapConfig.setEvictionPolicy(EvictionPolicy.LRU);
mapConfig.setMaxSizeConfig(new MaxSizeConfig(0, MaxSizeConfig.MaxSizePolicy.USED_HEAP_SIZE));
return mapConfig;
}
}
最后是一个实体示例
@Entity
@Table(name = "Banque")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Banque implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "Code")
private Integer code;
@Basic(optional = false)
@NotNull
@Size(min = 1, max = 150)
@Column(name = "Designation")
private String designation;
@OneToMany(mappedBy = "codeBanque")
@JsonBackReference
private Collection<Societe> societeCollection;
public Banque() {
}
public Banque(Integer code) {
this.code = code;
}
public Banque(Integer code, String designation) {
this.code = code;
this.designation = designation;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getDesignation() {
return designation;
}
public void setDesignation(String designation) {
this.designation = designation;
}
public Collection<Societe> getSocieteCollection() {
return societeCollection;
}
public void setSocieteCollection(Collection<Societe> societeCollection) {
this.societeCollection = societeCollection;
}
@Override
public int hashCode() {
int hash = 0;
hash += (code != null ? code.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Banque)) {
return false;
}
Banque other = (Banque) object;
if ((this.code == null && other.code != null) || (this.code != null && !this.code.equals(other.code))) {
return false;
}
return true;
}
@Override
public String toString() {
return "com.csys.parametrage.domain.Banque[ code=" + code + " ]";
}
}
我成功了。您需要缓存集合。
我变了
@OneToMany(mappedBy = "codeBanque")
private Collection<Societe> societeCollection;
至
@Cache (usage=CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@OneToMany(fetch = FetchType.EAGER, mappedBy = "codeBanque")
private Collection<Societe> societeCollection;
正如 Neil Stevenson 在他的评论中所说,解决方案是使用 查询缓存 。
为此,我已将 hibernate.cache.use_query_cache
切换为 true,但我还指定休眠哪些查询必须使用 @QueryHints
进行缓存。
这是我存储库的代码
Repository("BanqueRepository")
public interface BanqueRepository extends JpaRepository<Banque, Integer> {
public Banque findByCode(Integer code);
@Override
@QueryHints({
@QueryHint(name = "org.hibernate.cacheable", value = "true")})
public List<Banque> findAll();
}
我目前在我的 springboot 应用程序(版本 1.5.2.RELEASE)中使用带 hazelcast 3.7.5 的休眠二级缓存。 每当我使用由 Spring Data Jpa 实现的 findAll() 方法时,hibernate 从数据库中检索数据,但是当我使用 findOne(id) 方法时,hibernate 从 chache 获取数据。有人可以解释这种奇怪的行为吗? 这是我的休眠配置
spring:
datasource:
url: jdbc:h2:file:./target/h2db/db/parametrage;DB_CLOSE_DELAY=-1;INIT=CREATE SCHEMA IF NOT EXISTS PARAM
username: sa
password:
jpa:
open-in-view: false
show-sql: true
hibernate:
ddl-auto: none
naming:
implicit-strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
properties:
hibernate.default_schema: PARAM
hibernate.id.new_generator_mappings: true
hibernate.cache.use_second_level_cache: true
hibernate.cache.use_query_cache: false
hibernate.generate_statistics: true
hibernate.cache.region.factory_class: com.hazelcast.hibernate.HazelcastCacheRegionFactory
hibernate.cache.hazelcast.instance_name: hazelcast
hibernate.cache.use_minimal_puts: true
hibernate.cache.hazelcast.use_lite_member: true
这是我的 hazelcast 配置
@Configuration
@EnableCaching
public class CacheConfiguration {
private final Logger log = LoggerFactory.getLogger(CacheConfiguration.class);
private final Environment env;
public CacheConfiguration(Environment env) {
this.env = env;
}
@Bean
public CacheManager cacheManager(HazelcastInstance hazelcastInstance) {
log.debug("Starting HazelcastCacheManager");
CacheManager cacheManager = new HazelcastCacheManager(hazelcastInstance);
return cacheManager;
}
@PreDestroy
public void destroy() {
log.info("Closing Cache Manager");
Hazelcast.shutdownAll();
}
@Bean
public HazelcastInstance hazelcastInstance() {
log.debug("Configuring Hazelcast");
Config config = new Config();
config.setInstanceName("hazelcast");
config.getNetworkConfig().setPort(5701);
config.getNetworkConfig().setPortAutoIncrement(true);
config.getNetworkConfig().getJoin().getAwsConfig().setEnabled(false);
config.getNetworkConfig().getJoin().getMulticastConfig().setEnabled(false);
config.getNetworkConfig().getJoin().getTcpIpConfig().addMember("localhost").setEnabled(true);
config.getMapConfigs().put("default", initializeDefaultMapConfig());
config.getManagementCenterConfig().
setUrl("http://localhost:8080/mancenter")
.setEnabled(true);
return Hazelcast.newHazelcastInstance(config);
}
private MapConfig initializeDefaultMapConfig() {
MapConfig mapConfig = new MapConfig();
mapConfig.setBackupCount(0);
mapConfig.setEvictionPolicy(EvictionPolicy.LRU);
mapConfig.setMaxSizeConfig(new MaxSizeConfig(0, MaxSizeConfig.MaxSizePolicy.USED_HEAP_SIZE));
return mapConfig;
}
}
最后是一个实体示例
@Entity
@Table(name = "Banque")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Banque implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "Code")
private Integer code;
@Basic(optional = false)
@NotNull
@Size(min = 1, max = 150)
@Column(name = "Designation")
private String designation;
@OneToMany(mappedBy = "codeBanque")
@JsonBackReference
private Collection<Societe> societeCollection;
public Banque() {
}
public Banque(Integer code) {
this.code = code;
}
public Banque(Integer code, String designation) {
this.code = code;
this.designation = designation;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getDesignation() {
return designation;
}
public void setDesignation(String designation) {
this.designation = designation;
}
public Collection<Societe> getSocieteCollection() {
return societeCollection;
}
public void setSocieteCollection(Collection<Societe> societeCollection) {
this.societeCollection = societeCollection;
}
@Override
public int hashCode() {
int hash = 0;
hash += (code != null ? code.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Banque)) {
return false;
}
Banque other = (Banque) object;
if ((this.code == null && other.code != null) || (this.code != null && !this.code.equals(other.code))) {
return false;
}
return true;
}
@Override
public String toString() {
return "com.csys.parametrage.domain.Banque[ code=" + code + " ]";
}
}
我成功了。您需要缓存集合。 我变了
@OneToMany(mappedBy = "codeBanque")
private Collection<Societe> societeCollection;
至
@Cache (usage=CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@OneToMany(fetch = FetchType.EAGER, mappedBy = "codeBanque")
private Collection<Societe> societeCollection;
正如 Neil Stevenson 在他的评论中所说,解决方案是使用 查询缓存 。
为此,我已将 hibernate.cache.use_query_cache
切换为 true,但我还指定休眠哪些查询必须使用 @QueryHints
进行缓存。
这是我存储库的代码
Repository("BanqueRepository")
public interface BanqueRepository extends JpaRepository<Banque, Integer> {
public Banque findByCode(Integer code);
@Override
@QueryHints({
@QueryHint(name = "org.hibernate.cacheable", value = "true")})
public List<Banque> findAll();
}