29 votes

JPA utilisant plusieurs schémas de base de données

Je rencontre un petit problème avec une question particulière en utilisant JPA/Spring:

Comment puis-je attribuer dynamiquement un schéma à une entité?

Nous avons TABLE1 qui appartient au schéma AD et TABLE2 qui est sous BD.

@Entity
@Table(name = "TABLE1", schema="S1D")
...

@Entity
@Table(name = "TABLE2", schema="S2D")
...

Les schémas ne peuvent pas être codés en dur dans un attribut d'annotation car cela dépend de l'environnement (Dev/Acc/Prd). (En acceptation, les schémas sont S1A et S2A)

Comment puis-je y parvenir? Est-il possible de spécifier des sortes de placeholders comme ceci:

@Entity
@Table(name = "TABLE1", schema="${schema1}")
...

@Entity
@Table(name = "TABLE2", schema="${schema2}")
...

afin que les schémas soient remplacés en fonction d'un fichier de propriétés résidant dans l'environnement?

Bien à vous

10voto

proca 2.0 Points 1476

J'ai eu le même problème que j'ai résolu avec un fichier persistence.xml dans lequel je fais référence aux fichiers orm.xml nécessaires dans lesquels j'ai déclaré le schéma de la base de données

    . . .
    ormOne.xml
    . . .

    . . .
    ormTwo.xml
    . . .

maintenant vous pouvez créer un EntityManagerFactory pour votre schéma particulier

EntityManagerFactory emf = Persistence.createEntityManagerFactory("schemaOne");

3voto

DataNucleus Points 12361

Une chose que vous pouvez faire si vous savez au déploiement est d'avoir 2 fichiers orm.xml. Un pour schema1 et un autre pour schema2 et ensuite dans le persistence.xml vous avez 2 persistence-units définis. Mettre des annotations est un anti-pattern si vous avez besoin de changer des choses comme le schéma

3voto

zistheman12 Points 1

J'ai posté ceci sur github mais je le poste également ici.

J'ai trouvé qu'il est possible d'accomplir une configuration de schéma dynamique pour plusieurs schémas dans différents environnements en remplacant la stratégie de nommage physique.

Prenons par exemple deux entités comme celles-ci qui sont configurées pour deux schémas différents -

@Entity
@Table(name="TABLE1", schema="schema1")
public class FooEntity implements Serializable {
    ...
}

@Entity
@Table(name="TABLE2", schema="schema2")
public class BarEntity implements Serializable {
    ...
}

Commencez par créer une configuration dans votre fichier application.yml:

multischema:
  config:
    schema1: FIRSTSCHEMA
    schema2: SECONDSCHEMA

Liez-le à un bean ConfigurationProperties

@Component
@ConfigurationProperties("multischema")
public class MultiSchemaConfigurationProperties {

    private Map config;

    public void setConfig(Map config) {
        this.config = config;
    }

    public Map getConfig() {
        return config;
    }

}

Créez une stratégie de nommage physique personnalisée qui injecte MultiSchemaConfigurationProperties et étend la stratégie par défaut de Spring Boot pour votre version. Dans ce cas, j'utilise Spring Boot 2.6.4 qui utilise CamelCaseToUnderscoresNamingStrategy.

@Component
public class MultiSchemaPhysicalNamingStrategy extends CamelCaseToUnderscoresNamingStrategy {

    private final MultiSchemaConfigurationProperties schemaConfiguration;

    public MultiSchemaPhysicalNamingStrategy(MultiSchemaConfigurationProperties schemaConfiguration) {
        this.schemaConfiguration = schemaConfiguration;
    }

    @Override
    public Identifier toPhysicalSchemaName(Identifier name, JdbcEnvironment jdbcEnvironment) {
        if(name != null) {
            Identifier identifier = super.getIdentifier(schemaConfiguration.getConfig()
                    .get(name.getText()), name.isQuoted(), jdbcEnvironment);
            return super.toPhysicalSchemaName(identifier, jdbcEnvironment);
        }
        return name;
    }

}

Lorsque l'application démarre, Hibernate invoquera la stratégie de nommage physique personnalisée pour appliquer la règle de nommage physique pour votre schéma en utilisant la configuration fournie dans application.yml. https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto.data-access.configure-hibernate-naming-strategy

"schema1" dans FooEntity sera remplacé par la valeur "firstschema" et "schema2" dans BarEntity sera remplacé par la valeur "secondschema".

2voto

user3092746 Points 1

Essayez ce qui suit:

puplic class MyClass {
  public static final String S1D="S1D";
  public static final String S2D="S2D";
}

@Entity
@Table(name = "TABLE1", schema=MyClass.S1D)
...

@Entity
@Table(name = "TABLE2", schema=MyClass.S2D)
...

1voto

Dominik Points 717

Vous pourriez avoir deux déclarations de DataSource (une pour chaque schéma) dans votre context.xml et définir deux unités de persistance en utilisant ces datasources. Le context.xml peut alors être différent sur les serveurs d'application des différents environnements.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X