首页 > 解决方案 > Spring JPA - 具有多个 JNDI 的单个存储库类

问题描述

我正在使用 Spring JPA Repository 连接到 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 配置来配置数据源。目前它只有一个 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)。但我不想要这个解决方案,而是想要使用单个存储库包和相同的存储库类。

标签: springjpaspring-data-jpajndi

解决方案


对我有用的解决方案。

1)为管理员用户和应用程序用户分别创建了一个单独的配置类

2)为管理员用户和应用程序用户创建了单独的实体管理器引用

3)通过java代码并使用各自的实体管理器实例化相同的Repositoy类(不使用@Repository注解)

@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();
}

推荐阅读