0

我正在使用spring-boot-data-jpahazelcast开发Spring Boot 2.4.1项目。我正在尝试设置一个可以读取数据库的分布式地图。我已经实现了,但是当我尝试运行应用程序时,由于循环依赖,它无法启动。似乎 JpaRepository 首先需要 HazelcastInstance 可用,但 HazelcastInstance 需要 MapLoader ,而 MapLoader 又需要 JpaRepository 准备好。至少从日志和这篇文章来看是这样的。com.hazelcast.map.MapLoader

有谁知道如何解决这个问题?

pom.xml

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.4.1</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

...

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<dependency>
    <groupId>com.hazelcast</groupId>
    <artifactId>hazelcast-all</artifactId>
    <version>4.1.1</version>
</dependency>

配置:

@Configuration
public class HZConfig {
    
    @Bean
    Config config(RVOLoader rvoLoader) {}
        Config config = new Config();
        config.getMapConfig("rvoMap").getMapStoreConfig().setImplementation(rvoLoader);
        config.getMapConfig("rvoMap").getMapStoreConfig()
            .setInitialLoadMode(MapStoreConfig.InitialLoadMode.EAGER);

        return config;
    }

    @Bean
    HazelcastInstance hazelcastInstance(Config config) {
        HazelcastInstance hz = Hazelcast.newHazelcastInstance(config);
        return hz;
    }
}

地图加载器

@Component
public class MyResourceMapLoader implements MapLoader<Long, MyResource> {
    
    private final MyResourceRepository repo;

    public MyResourceMapLoader(MyResourceRepository repo) {
        this.repo = repo;
    }

    @Override
    public MyResource load(Long key) {
        return this.repo.findById(key).orElse(null);
    }

    @Override
    public Map<Long, MyResource> loadAll(Collection<Long> keys) {
        Map<Long, MyResource> myResourceMap = new HashMap<>();
        for (Long key : keys) {
            MyResource myResource = this.load(key);
            if (myResource != null) {
                myResourceMap.put(key, myResource);
            }
        }
        return myResourceMap;
    }

    @Override
    public Iterable<Long> loadAllKeys() {
        return this.repo.findAllIds();
    }
}   

JpaRepository

@Repository
public interface MyResourceRepository extends JpaRepository<MyResource, Long> {

    List<MyResource> findAll();

    @Query("SELECT m.id from MyResource m")
    Iterable<Long> findAllIds();

}
4

1 回答 1

1

一种解决方案,

@Bean
public Config config(YourMapStoreFactory yourMapStoreFactory) {
    ...
    config.getMapConfig("rvoMap").getMapStoreConfig().setFactoryImplementation(yourMapStoreFactory);

使 Map Store Factory 成为一个组件,而不是 Map Store

@Component
public class YourMapStoreFactory implements MapStoreFactory {

    @Autowired
    private MyResourceRepository repo;

    public MapLoader newMapStore(String mapName, Properties properties) {
        if (mapName.equals("rvoMap") {
            return new MyResourceMapLoader(repo);
于 2021-01-16T16:55:14.567 回答