1

我解释一下我的情况:SpringBoot + Hibernate + Multitenant (DB master + DB for tenant) + Postgressql。我有两种数据源配置,一种用于主数据库,一种用于每个客户端的数据库。

当我需要进行本机查询时,我的问题就开始了。我需要重新启动数据库序列。但我不太清楚如何恢复会话工厂。在我的身份验证中,我识别用户并设置租户持有人

public class JWTAuthorizationFilter extends BasicAuthenticationFilter {

private IUsuario userService;
private IUsuarioSucursalRol usrService;
private IEquipoMaster equipoService;

public JWTAuthorizationFilter(AuthenticationManager authManager, IUsuario userService,
        IUsuarioSucursalRol usrService, IEquipoMaster equipoService) {
    super(authManager);
    this.userService = userService;
    this.usrService = usrService;
    this.equipoService = equipoService;
}

@Override
protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain)
        throws IOException, ServletException {

    String header = req.getHeader(HEADER_AUTHORIZACION_KEY);
    if (header == null || !header.startsWith(TOKEN_BEARER_PREFIX)) {
        chain.doFilter(req, res);
        return;
    }

    UsernamePasswordAuthenticationToken authentication = getAuthentication(header);

    SecurityContextHolder.getContext().setAuthentication(authentication); // Asigna
                                                                            // UsernamePasswordAuthenticationToken

    chain.doFilter(req, res);
}



private UsernamePasswordAuthenticationToken isUser(String token, String user) {
    //// Valida que el token del USUARIO y generara el
    //// UsernamePasswordAuthenticationToken
    try {
        Integer tenantint = obtainTenant(token); // Obtiene el tenant del token
        if (tenantint != null || tenantint != 0) { /// Valida que no venga un token erroneo sin tenant
            String tenant = String.valueOf(tenantint);
            TenantContextHolder.setTenantId(tenant); /// Coloca la base de datos
            Usuario finduser = userService.findUsuario(user, tenantint); // Busca el usuario
            if (finduser != null) {
                if (finduser.getFechaBaja() == null) { /// Valida que no este dado de baja el usuario

                    boolean respuesta = usrService.isAdmin(finduser.getIdUsuario());
                    Set<GrantedAuthority> grantedAuthorities = new HashSet<>();

                    if (respuesta) { // Es un admin
                        grantedAuthorities.add(new SimpleGrantedAuthority("ADMINISTRADOR"));
                        System.out.println("IS ADMINISTRADOR");
                    } else if (usrService.isUser((int) finduser.getIdUsuario())) { /// Es un usuario
                        grantedAuthorities.add(new SimpleGrantedAuthority("USUARIO"));
                        System.out.println("IS USUARIO");

                    } else { // Entonces es un vendedor por defecto
                        grantedAuthorities.add(new SimpleGrantedAuthority("VENDEDOR"));
                        System.out.println("IS VENDEDOR");
                    }

                    return new UsernamePasswordAuthenticationToken(user, null, grantedAuthorities);
                }
            }
        }
    } catch (Exception e) {
        // TODO: handle exception

    }
    return null;
}}

然后,JpaRepository 负责在正确的数据库中执行查询。但是,我怎么能通过执行本机查询来做同样的事情呢?还有另一种方法可以做到这一点吗?

更新

更多代码:

public class CurrentTenantIdentifierResolverImpl implements CurrentTenantIdentifierResolver {

private static final String DEFAULT_TENANT_ID = "tenant_standar";

@Override
public String resolveCurrentTenantIdentifier() {
    String tenant = TenantContextHolder.getTenant();
    return StringUtils.isNotBlank(tenant) ? tenant : DEFAULT_TENANT_ID;
}

@Override
public boolean validateExistingCurrentSessions() {
    return true;
}}





@Configuration
public class DataSourceBasedMultiTenantConnectionProviderImpl
        extends AbstractDataSourceBasedMultiTenantConnectionProviderImpl {

    private static final long serialVersionUID = 1L;

    /**
     * Injected MasterTenantRepository to access the tenant information from the
     * master_tenant table
     */
    @Autowired
    private ITenant masterTenantRepo;

    @Autowired
    private IBaseDatos masterdberepo;

    /**
     * Map to store the tenant ids as key and the data source as the value
     */
    private Map<String, DataSource> dataSourcesMtApp = new TreeMap<>();

    @Override
    protected DataSource selectAnyDataSource() {
        // This method is called more than once. So check if the data source map
        // is empty. If it is then rescan master_tenant table for all tenant
        // entries.
        if (dataSourcesMtApp.isEmpty()) {
            List<Tenant> masterTenants = masterTenantRepo.findAll();
            for (Tenant masterTenant : masterTenants) {
                BaseDatos base = masterdberepo.findDatosBaseTenant(masterTenant);
                dataSourcesMtApp.put(String.valueOf(base.getIdTenant().getIdTenant()),
                        DataSourceUtil.createAndConfigureDataSource(base));
            }
        }
        return this.dataSourcesMtApp.values().iterator().next();
    }

    protected String selectTenantDataSource(DataSource datasource) {
        // This method is called more than once. So check if the data source map
        // is empty. If it is then rescan master_tenant table for all tenant
        // entries.
        String tenant = "";
        while (dataSourcesMtApp.keySet().iterator().hasNext()) {
            tenant = dataSourcesMtApp.keySet().iterator().next();
            if (dataSourcesMtApp.get(tenant).equals(datasource)) {
                break;
            }
        }

        return tenant;
    }

    @Override
    public Connection getConnection(String tenantIdentifier) throws SQLException {
        // TODO Auto-generated method stub
        return super.getConnection(tenantIdentifier);
    }

    @Override
    protected DataSource selectDataSource(String tenantIdentifier) {
        // If the requested tenant id is not present check for it in the master
        // database 'master_tenant' table

        tenantIdentifier = initializeTenantIfLost(tenantIdentifier);

        if (!this.dataSourcesMtApp.containsKey(tenantIdentifier)) {
            List<Tenant> masterTenants = masterTenantRepo.findAll();
            for (Tenant masterTenant : masterTenants) {

                BaseDatos base = masterdberepo.findDatosBaseTenant(masterTenant);
                dataSourcesMtApp.put(String.valueOf(base.getIdTenant().getIdTenant()),
                        DataSourceUtil.createAndConfigureDataSource(base));

            }
        }
        return this.dataSourcesMtApp.get(tenantIdentifier);
    }

    /**
     * Initialize tenantId based on the logged in user if the tenant Id got lost in
     * after form submission in a user session.
     * 
     * @param tenantIdentifier
     * @return tenantIdentifier
     */
    private String initializeTenantIfLost(String tenantIdentifier) {
        if (TenantContextHolder.getTenant() == null) {

            SecurityContext securityContext = SecurityContextHolder.getContext();
            Authentication authentication = securityContext.getAuthentication();
            CustomUserDetails customUserDetails = null;
            if (authentication != null) {
                Object principal = authentication.getPrincipal();
                customUserDetails = principal instanceof CustomUserDetails ? (CustomUserDetails) principal : null;
            }
            TenantContextHolder.setTenantId(customUserDetails.getTenant().getNombre());
        }

        if (tenantIdentifier != TenantContextHolder.getTenant()) {
            tenantIdentifier = TenantContextHolder.getTenant();
        }
        return tenantIdentifier;
    }

}








@Configuration
@EnableTransactionManagement
@ComponentScan(basePackages = { "com.kretz.gestion.equipos.tenant.repository",
        "com.kretz.gestion.equipos.tenant.model" })
@EnableJpaRepositories(basePackages = {
        "com.kretz.gestion.equipos.tenant.repository" }, entityManagerFactoryRef = "tenantEntityManagerFactory", transactionManagerRef = "tenantTransactionManager")
public class TenantDatabaseConfig implements ApplicationListener<ApplicationReadyEvent> {

    @Bean(name = "tenantJpaVendorAdapter")
    public JpaVendorAdapter jpaVendorAdapter() {
        return new HibernateJpaVendorAdapter();
    }

    @Bean(name = "tenantTransactionManager")
    public JpaTransactionManager transactionManager(
            @Qualifier("tenantEntityManagerFactory") EntityManagerFactory tenantEntityManager) {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(tenantEntityManager);
        return transactionManager;
    }

    /**
     * The multi tenant connection provider
     * 
     * @return
     */
    @Bean(name = "datasourceBasedMultitenantConnectionProvider")
    @ConditionalOnBean(name = "masterEntityManagerFactory")
    public MultiTenantConnectionProvider multiTenantConnectionProvider() {
        // Autowires the multi connection provider
        return crearDataSource();

    }

    @Bean(name = "datasource")
    public DataSourceBasedMultiTenantConnectionProviderImpl crearDataSource() {

        return new DataSourceBasedMultiTenantConnectionProviderImpl();

    }

    /**
     * The current tenant identifier resolver
     * 
     * @return
     */
    @Bean(name = "currentTenantIdentifierResolver")
    public CurrentTenantIdentifierResolver currentTenantIdentifierResolver() {
        return new CurrentTenantIdentifierResolverImpl();
    }

    /**
     * Creates the entity manager factory bean which is required to access the JPA
     * functionalities provided by the JPA persistence provider, i.e. Hibernate in
     * this case.
     * 
     * @param connectionProvider
     * @param tenantResolver
     * @return
     */
    @Bean(name = "tenantEntityManagerFactory")
    @ConditionalOnBean(name = "datasourceBasedMultitenantConnectionProvider")
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(
            @Qualifier("datasourceBasedMultitenantConnectionProvider") MultiTenantConnectionProvider connectionProvider,
            @Qualifier("currentTenantIdentifierResolver") CurrentTenantIdentifierResolver tenantResolver) {

        System.out.println(" LocalContainerEntityManagerFactoryBean PASO");
        LocalContainerEntityManagerFactoryBean emfBean = new LocalContainerEntityManagerFactoryBean();
        // All tenant related entities, repositories and service classes must be scanned
        emfBean.setPackagesToScan(
                new String[] { Empresa.class.getPackage().getName(), IEmpresa.class.getPackage().getName() });
        emfBean.setJpaVendorAdapter(jpaVendorAdapter());
        emfBean.setPersistenceUnitName("tenantdb-persistence-unit");
        Map<String, Object> properties = new HashMap<>();
        properties.put(org.hibernate.cfg.Environment.MULTI_TENANT, MultiTenancyStrategy.DATABASE);
        properties.put(org.hibernate.cfg.Environment.MULTI_TENANT_CONNECTION_PROVIDER, connectionProvider);
        properties.put(org.hibernate.cfg.Environment.MULTI_TENANT_IDENTIFIER_RESOLVER, tenantResolver);
        // ImprovedNamingStrategy is deprecated and unsupported in Hibernate 5
        // properties.put("hibernate.ejb.naming_strategy",
        // "org.hibernate.cfg.ImprovedNamingStrategy");
        properties.put(org.hibernate.cfg.Environment.DIALECT, "org.hibernate.dialect.PostgreSQL95Dialect"); // LUISINA
        properties.put(org.hibernate.cfg.Environment.SHOW_SQL, true);
        properties.put(org.hibernate.cfg.Environment.FORMAT_SQL, true);
        properties.put(org.hibernate.cfg.Environment.ENABLE_LAZY_LOAD_NO_TRANS, true);
        // properties.put(org.hibernate.cfg.Environment.USE_TRANSIENT_ANNOTATION, true);

        properties.put(org.hibernate.cfg.Environment.HBM2DDL_AUTO, "validate");
        properties.put(org.hibernate.cfg.Environment.NON_CONTEXTUAL_LOB_CREATION, true);

        properties.put(org.hibernate.cfg.Environment.C3P0_MAX_SIZE, 20);
        properties.put(org.hibernate.cfg.Environment.C3P0_MIN_SIZE, 5);
        properties.put(org.hibernate.cfg.Environment.C3P0_MAX_STATEMENTS, 50);
        properties.put(org.hibernate.cfg.Environment.C3P0_ACQUIRE_INCREMENT, 5);
        properties.put(org.hibernate.cfg.Environment.C3P0_TIMEOUT, 1800);

        emfBean.setJpaPropertyMap(properties);
        return emfBean;
    }

    @Autowired
    @Qualifier("datasourceBasedMultitenantConnectionProvider")
    MultiTenantConnectionProvider connectionProvider;

    @Override
    @ConditionalOnBean(name = "datasourceBasedMultitenantConnectionProvider")
    public void onApplicationEvent(ApplicationReadyEvent event) {
    }

}

谢谢。

4

0 回答 0