【问题标题】:Hazelcast Repository Still queries the DatabaseHazelcast Repository 仍然查询数据库
【发布时间】:2020-09-26 05:29:29
【问题描述】:

我正在开发一个 Spring Boot 项目。在那,我有一个名为 ProductMap 的实体,我想将其保存在缓存中。我使用 MapLoader 完成了这项工作,并为地图定义了如下配置。

@Bean
    public Config hazelcastConfig() {
        return new Config().setInstanceName("hazelcast-instance").addMapConfig(
                new MapConfig().setName("ProductMap")
                        .setMapStoreConfig(
                                new MapStoreConfig().setEnabled(true).setInitialLoadMode(MapStoreConfig.InitialLoadMode.EAGER)
                                        .setClassName("com.hazelcast.example.HzTest.config.ProductMapLoader")
                        ));
    }

ProductMap 实体:

@Data
@Entity
@KeySpace("ProductMap")
@Table
public class ProductMap implements Serializable {

    @Id
    @org.springframework.data.annotation.Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer Id;

    private String name;

    private Integer category;

    private Integer productType;
}

ProductMapLoader:

@Log4j2
@Component
public class ProductMapLoader implements MapLoader<Integer, ProductMap>, ApplicationContextAware {

    private static ProductMapRepository productMapRepository;

    @Override
    public synchronized ProductMap load(Integer integer) {
        System.out.println("Load::" + integer);
        return productMapRepository.findById(integer).get();
    }

    @Override
    public synchronized Map<Integer, ProductMap> loadAll(Collection<Integer> collection) {
        Map<Integer, ProductMap> result = new HashMap<>();
        for (Integer key : collection) {
            ProductMap productMap = this.load(key);
            if (productMap != null) {
                result.put(key, productMap);
            }
        }
        return result;
    }

    @Override
    public synchronized Iterable<Integer> loadAllKeys() {
        System.out.println("load all keys" + productMapRepository);
        return productMapRepository.findAllProdMapKeys();
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        productMapRepository = applicationContext.getBean(ProductMapRepository.class);
    }
}

我在启动时加载缓存,

@PostConstruct
public void Init() {
       IMap map = hazelcastInstance.getMap("ProductMap");  // this will load the cache 
}

在里面还创建了一个HazelcastRepository,

public interface ProductMapKvRepo extends KeyValueRepository<ProductMap, Integer> {

    List<ProductMap> findByProductType(Integer productType);
}

在我的一种服务方法中,它调用了productMapKvRepo.findAll()productMapKvRepo.findByProductType(1). 但存储库仍然查询数据库。

Hibernate: select productmap0_.id as id1_0_, productmap0_.category as category2_0_, productmap0_.name as name3_0_, productmap0_.product_type as product_4_0_ from product_map productmap0_
Hibernate: select productmap0_.id as id1_0_, productmap0_.category as category2_0_, productmap0_.name as name3_0_, productmap0_.product_type as product_4_0_ from product_map productmap0_ where productmap0_.product_type=?

使用的依赖项:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-cache</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>com.hazelcast</groupId>
        <artifactId>hazelcast</artifactId>
        <version>3.12.7</version>
    </dependency>
    <dependency>
        <groupId>com.hazelcast</groupId>
        <artifactId>hazelcast-client</artifactId>
        <version>3.12.7</version>
    </dependency>
    <dependency>
        <groupId>com.hazelcast</groupId>
        <artifactId>spring-data-hazelcast</artifactId>
        <version>2.2.5</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.postgresql</groupId>
        <artifactId>postgresql</artifactId>
        <version>42.2.13</version>
    </dependency>
</dependencies>

谁能告诉我这里出了什么问题,我该怎么办?

【问题讨论】:

    标签: spring-data hazelcast second-level-cache


    【解决方案1】:

    您的日志表明您的 Spring Data 存储库是 Hibernate 支持的,这意味着您的项目配置错误。 Spring Data Hazelcast 不使用 Hibernate 从 Hazelcast IMDG 集群中读取数据。

    如果打算(最有可能)使用 Hibernate,那么您应该考虑将其原生二级缓存功能与 Hazelcast 一起使用,而不是将 Spring Data 存储库包装在 MapLoader 中。您可以找到示例here

    但是,如果您想通过 MapLoader 应用 read-through 缓存模式,则需要使用 spring-data-hazelcast 工件从 Hazelcast 读取数据直接集群。

    【讨论】:

    • 嗨,格热戈兹。我在上面的问题中添加了我的依赖项。您能帮我如何应用通过缓存模式读取吗?我需要配置 Hazelcast 吗?
    • @AjaySankaran 我认为你对类路径的依赖太多了,这可能会产生额外的混乱。要实现通读,您需要两件事:1)带有自定义 MapLoader 实现的 Hazelcast(我建议在没有 Hibernate 的情况下这样做,因为它有很多额外的复杂性) 2)从 Hazelcast 读取数据的东西,这可以通过一个普通的 Hazelcast 客户端或 Spring Data
    • 你想使用嵌入式 Hazelcast 实例还是分开?
    • 我想使用嵌入式 hazelcast 实例。这是一个虚拟项目,我正在其中复制另一个项目。在那个项目中,我使用的是休眠 2 级缓存以及 spring data hazelcast。背后的想法是休眠级别 2 缓存对于具有太多映射的实体很有用(它会在保存时查看缓存而不是 DB)。虽然我在实体是由其他列而不是 ID 查询的情况下使用 spring data hazelcast。
    • 我同时使用两者的原因是在应用程序加载期间,我将一些实体加载到缓存中。在该加载中,一些由休眠二级缓存管理。但问题是,如果调用 findByProductType 或 findByCategory 之类的方法,hibernate 仍然会查询数据库而不是缓存,因为它只知道 id。
    【解决方案2】:

    当我使用 Spring Boot v2.1.3.RELEASE 和 Spring v5.1.5.RELEASE 时,spring 正在为两个存储库注入 SimpleJpaRepository 类型: MyStandardRepositoryMyHazelCastRepository,只有 @EnableHazelcastRepositories 存在

    @EnableJpaRepositories 也添加到我的HazelcastConfiguration 类中:

    spring 然后将SimpleKeyValueRepository bean 类型注入MyHazelCastRepository

    @Configuration
    @EnableHazelcastRepositories(basePackages = {"com.test.repository.hazelcast"})
    @EnableJpaRepositories(basePackages = {"com.test.repository.dao"})
    
    public class HazelcastConfiguration {
        
        @Bean
        HazelcastInstance hazelcastInstance() {
             return Hazelcast.newHazelcastInstance();
        }
        @Bean
        public KeyValueOperations keyValueTemplate() {
            return new KeyValueTemplate(new HazelcastKeyValueAdapter(hazelcastInstance()));
        }
        @Bean
         public HazelcastKeyValueAdapter  hazelcastKeyValueAdapter(HazelcastInstance hzInstance) {
            return new HazelcastKeyValueAdapter(hzInstance);
         }
         
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-07-27
      • 2020-10-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-19
      • 2018-01-10
      • 1970-01-01
      相关资源
      最近更新 更多