skip to Main Content

I want to use both Redis and Mongo with repository manner (I do not want to use spring cache annotations but repository methods).

I annotate the main class with the following annotations.

@EnableMongoRepositories(basePackageClass = PersistencyRepository.class)
@EnableRedisRepositories(basePackageClass = CacheRepository.class)
@SpringBootApplication

Repos

public interface PersistencyRepository extends CrudRepository<Store, String> {}

public interface CacheRepository extends MongoRepository<Store, String> {}

Now, I am getting the following error.

The bean "cacheRepository" defined in com.repository.CacheRepository defined in @EnableMongoRepositories declared on StoreApplication, could not be registered. A bean with that name has already been defined in com.repository.CacheRepository defined in @EnableRedisRepositories declared on StoreApplication and overriding is disabled. 

How can I use repos of differenet databases (mongo, redis)?

2

Answers


  1. You extended the wrong repository interface (MongoRepository) on CacheRepository try extending CrudRepository instead.

    Also, your mongo and redis entities should be separated to different packages, usually I just went with com.my.company.entity.mongo and com.my.company.entity.redis for each.

    After that, you need to update those Configuration annotations. A better package design, instead of putting all annotations on Main is putting them on a separate package, then putting those annotations there. This has an added benefit of clearly splitting each configurations for what they actually do

    for example:

    package com.your.company.configuration;
    
    import com.your.company.configuration.properties.ApplicationProperties;
    import com.your.company.entity.mongo.BaseDocument;
    import com.your.company.entity.postgres.BaseEntity;
    import com.your.company.entity.redis.BaseHash;
    import com.your.company.repository.mongo.BaseMongoRepository;
    import com.your.company.repository.postgres.BaseJpaRepository;
    import com.your.company.repository.redis.BaseRedisRepository;
    import org.springframework.boot.context.properties.EnableConfigurationProperties;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
    import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
    import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;
    import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    import org.springframework.security.crypto.password.PasswordEncoder;
    
    @Configuration
    @EnableConfigurationProperties(ApplicationProperties.class)
    @EnableJpaRepositories(basePackageClasses = {BaseEntity.class, BaseJpaRepository.class})
    @EnableMongoRepositories(basePackageClasses = {BaseDocument.class,
            BaseMongoRepository.class}, repositoryFactoryBeanClass = EnhancedMongoRepositoryFactoryBean.class)
    @EnableRedisRepositories(basePackageClasses = {BaseHash.class, BaseRedisRepository.class})
    public class BasicConfiguration {
    
        @Bean
        public PasswordEncoder passwordEncoder() {
            return new BCryptPasswordEncoder();
        }
    }
    

    The above is only an example, usually I would split them further into one class each within the same package with names that describes what they are actually configuring, for example: MongoConfiguration.java, JpaConfiguration.java, etc. Note if you decide to go with that design, you need the @Configuration annotation in each of the separate classes

    Login or Signup to reply.
  2. I believe the main issue here is that both of your interfaces PersistencyRepository and CacheRepository are in the same package, and your configurations are both scanning the same package for Spring Data Repository interfaces, creating duplicate bean names. You should separate these repositories into their own packages.

    It’s important to note that basePackageClasses scans the whole package for applicable interfaces. See the docs for EnableMongoRepositories.basePackageClasses (source):

    Type-safe alternative to basePackages() for specifying the packages to scan for annotated components. The package of each class specified will be scanned. Consider creating a special no-op marker class or interface in each package that serves no purpose other than being referenced by this attribute.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search