Spring JPA - один класс репозитория с несколькими JNDI - PullRequest
0 голосов
/ 15 апреля 2020

Я использую репозиторий Spring JPA для подключения к Oracle.

Мой пакет репозитория com.demo.infrastructure.repository; Класс репозитория - StoreRepo. java

@Repository
public interface StoreRepo extends JpaRepository<StoreAttribute, String> {
    @Query("select storeAttributeName from StoreAttribute order by storeAttributeName asc")
    List<String> fetchAllStoreAttributeNames();

    List<StoreAttribute> findAllByOrderByStoreAttributeNameAsc();
}

Проблема : Я использую JNDI config для настройки источника данных. В настоящее время он имеет только одну запись JNDI. Теперь я хочу использовать два имени пользователя для одной и той же базы данных, одно с правами администратора (чтение и запись), а другое с доступом пользователя (только чтение). Оба этих пользователя будут иметь доступ к одному и тому же репозиторию и одному и тому же объекту.

Я попробовал уже имеющиеся решения, в которых используются два разных пакета репозитория для каждого источника данных. Но я хочу, чтобы репозиторий «StoreRepo» был таким же.


@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "entityManagerFactoryAdmin",
        basePackages = { "com.demo.infrastructure.repository" }
)
public class DataSourceAdminConfig {
    @Primary
    @Bean(name = "dataSourceAdmin")
    public DataSource dataSource() {
        return new JndiDataSourceLookup().getDataSource("jdbc/myds_admin");
    }

    @Primary
    @Bean(name = "entityManagerFactoryAdmin")
    public LocalContainerEntityManagerFactoryBean
    entityManagerFactory(
            EntityManagerFactoryBuilder builder,
            @Qualifier("dataSourceAdmin") DataSource dataSource
    ) {
        return builder.dataSource(dataSource).
                packages("com.demo.domain.model.entities").
                persistenceUnit("read-write").
                build();
    }

    @Primary
    @Bean(name = "transactionManagerAdmin")
    public PlatformTransactionManager transactionManager(
            @Qualifier("entityManagerFactoryAdmin") EntityManagerFactory
                    entityManagerFactory
    ) {
        return new JpaTransactionManager(entityManagerFactory);
    }
}

У меня должно быть два таких класса с различным пакетом (см. BasePackages). Но я не хочу, чтобы это решение вместо этого хотело использовать один пакет репозитория и тот же класс репозитория.

1 Ответ

0 голосов
/ 30 апреля 2020

Решение, которое сработало для меня.

1) Созданы отдельные классы конфигурации по одному для пользователя-администратора и пользователя приложения

2) Создан отдельный администратор сущностей, ссылающийся по одному для пользователя-администратора и пользователя приложения каждый

3) Создание того же класса Repositoy (без использования аннотации @Repository) с помощью кода java и с использованием соответствующего менеджера сущностей

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "entityManagerFactoryAdmin"
)
public class AdminUserConfig {
    @Primary
    @Bean(name = "dataSourceAdmin")
    public DataSource dataSourceAdmin(@Value("${spring.datasource.admin-user.jndi-name}") String key) {
        return new JndiDataSourceLookup().getDataSource(key);
    }

    @Primary
    @Bean(name = "entityManagerFactoryAdmin")
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryAdmin(
            EntityManagerFactoryBuilder builder,
            @Qualifier("dataSourceAdmin") DataSource dataSource
    ) {
        return builder.dataSource(dataSource).
                packages("com.demo.domain.model.entities").
                persistenceUnit("read-write").
                build();
    }

    @Bean(name = "entityManagerAdmin")
    public EntityManager     entityManagerAdmin(@Qualifier("entityManagerFactoryAdmin") EntityManagerFactory
            entityManagerFactory) {
        return     SharedEntityManagerCreator.createSharedEntityManager(entityManagerFactory);
    }

    @Bean(name = "adminRepository")
    public StoreRepo     readWriteDimStoreRepository(@Qualifier("jpaRepositoryFactoryAdmin")
            JpaRepositoryFactory repositoryFactory) {
        return repositoryFactory.getRepository(StoreRepo.class);
    }
}





@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "entityManagerFactoryApp"
)
public class AppUserConfig {
    @Primary
    @Bean(name = "dataSourceApp")
    public DataSource dataSourceApp(@Value("${spring.datasource.App-user.jndi-name}") String key) {
        return new JndiDataSourceLookup().getDataSource(key);
    }

    @Primary
    @Bean(name = "entityManagerFactoryApp")
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryApp(
            EntityManagerFactoryBuilder builder,
            @Qualifier("dataSourceApp") DataSource dataSource
    ) {
        return builder.dataSource(dataSource).
                packages("com.demo.domain.model.entities").
                persistenceUnit("read-only").
                build();
    }

    @Bean(name = "entityManagerAdmin")
    public EntityManager     entityManagerApp(@Qualifier("entityManagerFactoryApp") EntityManagerFactory
            entityManagerFactory) {
        return     SharedEntityManagerCreator.createSharedEntityManager(entityManagerFactory);
    }

    @Bean(name = "AppRepository")
    public StoreRepo     readOnlyStoreRepository(@Qualifier("jpaRepositoryFactoryApp")
            JpaRepositoryFactory repositoryFactory) {
        return repositoryFactory.getRepository(StoreRepo.class);
    }
}


//@Repository
public interface StoreRepo extends JpaRepository<StoreAttribute, String> {
    @Query("select storeAttributeName from StoreAttribute order by 
storeAttributeName asc")
    List<String> fetchAllStoreAttributeNames();

    List<StoreAttribute> findAllByOrderByStoreAttributeNameAsc();
}
...