栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

具有单个域对象和多个数据源的SpringBoot

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

具有单个域对象和多个数据源的SpringBoot

我设法提出了一些解决方案来完成此任务。

选项1-多租户

我认为多租户方法似乎是最干净的方法,同时仍使每个租户都拥有自己的数据库。

目录结构

org.company.project    - ApplicationMain        |_config - DatasourceConfiguration - WebMvcConfig        |_routing - TenantContext - TenantInterceptor - TenantSourceRouter        |_domain - Person        |_repository |_ PersonRepository        |_web -APIController

数据源配置

@Configuration@EnableTransactionManagementpublic class DatasourceConfiguration {    @Resource    private Environment env;    @Bean    public DataSource dataSource() {        AbstractRoutingDataSource dataSource = new TenantSourceRouter();        Map<Object, Object> targetDataSources = new HashMap<>();        targetDataSources.put("ALBANY", albanyDatasource());        targetDataSources.put("BUFFALO", buffaloDatasource());        dataSource.setTargetDataSources(targetDataSources);        dataSource.setDefaultTargetDataSource(albanyDatasource());        return dataSource;    }    public DataSource albanyDatasource() {        DriverManagerDataSource dataSource = new DriverManagerDataSource();        dataSource.setDriverClassName(env.getProperty("company.datasource.driver-class-name"));        dataSource.setUrl(env.getProperty("company.datasource.albany.jdbc-url"));        dataSource.setUsername(env.getProperty("company.datasource.albany.username"));        dataSource.setPassword(env.getProperty("company.datasource.albany.password"));        return dataSource;    }    public DataSource buffaloDatasource() {        DriverManagerDataSource dataSource = new DriverManagerDataSource();        dataSource.setDriverClassName(env.getProperty("company.datasource.driver-class-name"));        dataSource.setUrl(env.getProperty("company.datasource.buffalo.jdbc-url"));        dataSource.setUsername(env.getProperty("company.datasource.buffalo.username"));        dataSource.setPassword(env.getProperty("company.datasource.buffalo.password"));        return dataSource;    }}

域实体-人

@Entitypublic class Person {    @Id    private String id;    private String name;}

人资料库

public interface PersonRepository extends JpaRepository<Person, String> {}

租户上下文

public class TenantContext {    private static final ThreadLocal<String> currentTenant  = new ThreadLocal<>();    public static void setCurrentTenant(String tenant) {        Assert.notNull(tenant, "clientDatabase cannot be null");        currentTenant.set(tenant);    }    public static String getClientDatabase() {        return currentTenant .get();    }    public static void clear() {        currentTenant .remove();    }}

租户上下文

public class TenantSourceRouter extends AbstractRoutingDataSource {    @Override    protected Object determineCurrentLookupKey() {        return TenantContext.getClientDatabase();    }}

TenantInterceptor- 我决定添加一个全局拦截器,在该拦截器中,您可以将请求标头“ X-TenantID”设置为所需的租户“
ALBANY”或“ BUFFALO”,而不必在逐个控制器的基础上进行处理。

@Componentpublic class TenantInterceptor extends HandlerInterceptorAdapter {    @Override    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {        String tenantId = request.getHeader("X-TenantID");        TenantContext.setCurrentTenant(tenantId);        return true;    }    @Override    public void postHandle( HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {        TenantContext.clear();    }}

WebMvcConfig- 现在我们必须向WebMvc注册拦截器

@Configurationpublic class WebMvcConfig implements WebMvcConfigurer {    @Override    public void addInterceptors(InterceptorRegistry registry) {        registry.addInterceptor(new TenantInterceptor());    }}

APIController- 最后,我们创建控制器,在该控制器中访问存储库。

@RestController@RequestMapping("/api")public class APIController {    @Autowired    private PersonRepository personRepository;    @GetMapping("/{id}")    public Optional<Person> get(@PathVariable String id) {        return personRepository.findById(id);    }    @GetMapping("/")    public List<Person> getAll() {        return personRepository.findAll();    }}

application.yml

company:  datasource:    driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver    albany:      jdbc-url: ***      username: ***      password: ***    buffalo:      jdbc-url: ***      username: ***      password: ***

选项2-具有多个存储库的更传统的多租户

目录结构

org.company.project    - ApplicationMain        |_config - AlbanyDbConfiguration (datasource 1) - BuffaloDbConfiguration (datasource 2)        |_domain - Person        |_repository |_ albany     - PersonRepositoryAlbany (repository for datasource 1) |_ buffalo     - PersonRepositoryBuffalo (repository for datasource 2)        |_web -APIController

application.yml

spring:  datasource:    jdbc-url: ***    username: ***    password: ***buffalo:  datasource:    jdbc-url: ***    username: ***    password: ***

域实体-人

@Entitypublic class Person {    @Id    private String id;    private String name;}

存储库-PersonRepositoryAlbany *

public interface PersonRepositoryAlbany extends JpaRepository<Person, String>, JpaSpecificationExecutor<Person> {}

存储库-PersonRepositoryBuffalo *

public interface PersonRepositoryBuffalo extends JpaRepository<Person, String>, JpaSpecificationExecutor<Person> {}

数据源配置-AlbanyDbConfiguration

@Configuration@EnableJpaRepositories(        basePackages = { "org.company.project.repository.albany"},        entityManagerFactoryRef = "albanyEntityManagerFactory",        transactionManagerRef = "albanyTransactionManager")public class AlbanyDbConfiguration {    @Primary    @Bean(name = "dataSource")    @ConfigurationProperties(prefix = "spring.datasource")    public DataSource dataSource() {        return DataSourceBuilder.create().build();    }    @Primary    @Bean(name = "albanyEntityManagerFactory")    public LocalContainerEntityManagerFactoryBean        entityManagerFactory(EntityManagerFactoryBuilder builder, @Qualifier("dataSource") DataSource dataSource) {        return builder     .dataSource(dataSource)     .packages("org.company.project.domain")     .properties(jpaProperties())     .build();    }    public Map<String, Object> jpaProperties() {        Map<String, Object> props = new HashMap<>();        props.put("hibernate.physical_naming_strategy", SpringPhysicalNamingStrategy.class.getName());        props.put("hibernate.implicit_naming_strategy", SpringImplicitNamingStrategy.class.getName());        return props;    }    @Primary    @Bean(name = "albanyTransactionManager")    public PlatformTransactionManager transactionManager(@Qualifier("albanyEntityManagerFactory") EntityManagerFactory entityManagerFactory) {        return new JpaTransactionManager(entityManagerFactory);    }}

数据源配置-BuffaloDbConfiguration

@Configuration@EnableJpaRepositories(        basePackages = { "org.company.project.repository.buffalo"},        entityManagerFactoryRef = "buffaloEntityManagerFactory",        transactionManagerRef = "buffaloTransactionManager")public class BuffaloDbConfiguration {    @Bean(name = "buffaloDataSource")    @ConfigurationProperties(prefix = "buffalo.datasource")    public DataSource dataSource() {        return DataSourceBuilder.create().build();    }    @Bean(name = "buffaloEntityManagerFactory")    public LocalContainerEntityManagerFactoryBean    entityManagerFactory(EntityManagerFactoryBuilder builder, @Qualifier("buffaloDataSource") DataSource dataSource) {        return builder     .dataSource(dataSource)     .packages("org.company.project.domain")     .properties(jpaProperties())     .build();    }    public Map<String, Object> jpaProperties() {        Map<String, Object> props = new HashMap<>();        props.put("hibernate.physical_naming_strategy", SpringPhysicalNamingStrategy.class.getName());        props.put("hibernate.implicit_naming_strategy", SpringImplicitNamingStrategy.class.getName());        return props;    }    @Bean(name = "buffaloTransactionManager")    public PlatformTransactionManager transactionManager(@Qualifier("buffaloEntityManagerFactory") EntityManagerFactory entityManagerFactory) {        return new JpaTransactionManager(entityManagerFactory);    }}

Web控制器-APIController

@EnableTransactionManagement@RestController@RequestMapping("/api")public class APIController {    @Autowired    private PersonRepositoryAlbany personRepositoryAlbany;    @Autowired    private PersonRepositoryBuffalo personRepositoryBuffalo;    @GetMapping("/albany")    public List<Person> albany() {        return getPersonsAlbany();    }    @GetMapping("/buffalo")    public List<Person> buffalo() {        return getPersonsBuffalo();    }    @Transactional("albanyTransactionManager")    public List<Person> getPersonsAlbany() {        return personRepositoryAlbany.findAll();    }    @Transactional("buffaloTransactionManager")    public List<Person> getPersonsBuffalo() {        return personRepositoryBuffalo.findAll();    }}


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/635699.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号