Changement de schéma de base de données en cours d'exécution basée sur l'utilisateur connecté

J'ai lu beaucoup de questions et réponses à propos de la dynamique de la source de données de routage et ont mis en œuvre une solution à l'aide de AbstractRoutingDataSource et l'autre(voir ci-dessous). C'est très bien, mais nécessite codé en dur propriétés pour toutes les sources de données. Comme le nombre d'utilisateurs à l'aide de l'application augmente, ce n'est pas un moyen approprié de routage plus. Aussi il aurait besoin pour ajouter une entrée pour les propriétés à chaque fois qu'un nouvel utilisateur s'enregistre. La situation est comme suit

  • 1 serveur de base de données
  • de nombreux schémas sur ce serveur, chaque utilisateur dispose de son propre schéma.
  • J'ai seulement besoin de changer le nom du schéma en cours d'exécution
  • nom de schéma est retainable par utilisateur connecté

Je suis en utilisant spring boot 1.4.0 avec hibernate 5.1 et spring data jpa

Je ne peux pas trouver un moyen de modifier le schéma complètement de façon dynamique. Quelqu'un sait-il comment le faire au printemps?

EDIT:

Grâce à @Johannes Leimer réponse, j'ai eu un travail de mise.

Voici le code:

Utilisateur Fournisseur:

@Component
public class UserDetailsProvider {
    @Bean
    @Scope("prototype")
    public CustomUserDetails customUserDetails() {
        return (CustomUserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    }
}

UserSchemaAwareRoutingDatasource:

public class UserSchemaAwareRoutingDataSource extends AbstractDataSource {
@Inject
Provider<CustomUserDetails> customUserDetails;

@Inject
Environment env;
private LoadingCache<String, DataSource> dataSources = createCache();

@Override
public Connection getConnection() throws SQLException {
    try {
        return determineTargetDataSource().getConnection();
    } catch (ExecutionException e){
        e.printStackTrace();

        return null;
    }
}

@Override
public Connection getConnection(String username, String password) throws SQLException {
    System.out.println("getConnection" + username);
    System.out.println("getConnection2" + password);
    try {
        return determineTargetDataSource().getConnection(username, password);
    } catch (ExecutionException e) {
        e.printStackTrace();
        return null;
    }
}

private DataSource determineTargetDataSource() throws SQLException, ExecutionException {
    try {
        String schema = customUserDetails.get().getUserDatabase();
        return dataSources.get(schema);
    } catch (NullPointerException e) {
        e.printStackTrace();

        return dataSources.get("fooooo");
    }

}
  • ne voulez pas plonger profondément dans les choses, vous pouvez mettre de la logique dans la méthode qui retourne un prototype de source de données, les instances?
  • La droite. Un multi-schéma de base de données fait beaucoup plus de sens que d'un multi-serveur de base de données, qui est ce que votre question annoncés avant la modification.
  • Oui, modifié le texte, il a été missleading. Merci et désolé pour la mauvaise formulation! @DavidWallace
  • J'ai vraiment envie de connaître la réponse de la ce. J'ai une très grosse application qui a besoin de changer de schéma pour un travail particulier. Mais à chaque fois que ce même produit, il se bloque.
  • forum.printemps.io/forum/printemps-projets/data/... il couvre la plupart de la chose dont vous avez besoin. Le nom d'utilisateur, vous pouvez l'obtenir à partir du thread variable locale qui vous pouvez définir plus tôt.
  • le post est de huit ans et, malheureusement, ne convient pas à mes besoins
  • pouvez-vous expliquer exactement pourquoi la solution de ce thread ne correspond pas à vos souhaits? ThreadLocal contexte de l'approche est assez commun, et devrait couvrir votre cas.
  • Vous pouvez essayer primordial AbstractRoutingDataSource.determineTargetDataSource() Lien méthode pour avoir un comportement différent. Si la source de données n'est pas trouvé pour votre clé, puis en créer un que par le nom de l'utilisateur et de l'insérer dans la carte, qui contient toutes les sources de données.
  • Continuation pour le commentaire précédent Note Vous avez besoin d'ajouter une synchronisation correcte là pour répondre à tous les cas d'utilisation où les 2 fils de la demande pour la même source de données qui n'est pas encore créé et nous n'avons pas, en fin de compte même de la source de données à de multiples reprises.
  • Pourriez-vous s'il vous plaît partagez exemple comment la mettre en œuvre celui-ci.
  • Pourriez-vous s'il vous plaît partagez exemple comment la mettre en œuvre celui-ci.Il me serait utile si vous fournissez un exemple.voici mon problème stackoverflow.com/questions/51130898/...
  • pourriez-vous s'il vous plaît partager repo git de POC ?