Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple DataSource configuration #234

Open
mcherb opened this issue Apr 6, 2023 · 4 comments
Open

Multiple DataSource configuration #234

mcherb opened this issue Apr 6, 2023 · 4 comments
Labels
type: enhancement A general enhancement

Comments

@mcherb
Copy link

mcherb commented Apr 6, 2023

I have multiple datasources, each points to a different schema in the same database.

dsx.datasource.jdbc-url=jdbc:postgresql://localhost:5432/db?currentSchema=x
dsx.datasource.hikari.data-source-properties.currentSchema=x
dsy.datasource.jdbc-url=jdbc:postgresql://localhost:5432/db?currentSchema=y
dsy.datasource.hikari.data-source-properties.currentSchema=y
dsz.datasource.jdbc-url=jdbc:postgresql://localhost:5432/db?currentSchema=z
dsz.datasource.hikari.data-source-properties.currentSchema=z

I'm using the AutoConfigureEmbeddedDatabase annotation like so:

@AutoConfigureEmbeddedDatabase(provider = ZONKY, beanName = "xDataSource")
@AutoConfigureEmbeddedDatabase(provider = ZONKY, beanName = "yDataSource")
@AutoConfigureEmbeddedDatabase(provider = ZONKY, beanName = "zDataSource")

So far, so good

Beside, I have a sql query which is joining multiple schema together; something like :

select * from x.table x join y.table y on ...

EmbeddedDatabase will replace the original datasources whithout taking the original configuration (like the schema name).

From the documentation I've found that I can set currentSchema with some additional configuration :

zonky.test.database.postgres.client.properties.currentSchema=x

But his configuration will affect all the replaced dataSources. I'm I right ?

Is there a way to use the same configuration with the datasource bean name, for instance:

zonky.test.database.postgres.client.xDataSource.properties.currentSchema=x

@tomix26
Copy link
Collaborator

tomix26 commented Apr 8, 2023

The problem is that each @AutoConfigureEmbeddedDatabase annotation creates a new, completely independent postgres database. But if I understood you correctly, your goal is to have only one database, but with several schemas to be able to make select and join queries among these schemas. In this case, using a single @AutoConfigureEmbeddedDatabase annotation should be sufficient.

The annotation creates a common data source through which you can initialize the database and create the required schemas. However, the other data sources must be created manually, according to your needs. These data sources actually refer to the same database, but with different connection parameters. Since the target database and the data source parameters may change during the tests (to achieve the desired test isolation), the best approach is to create a data source wrapper that applies these parameters at the moment of creating a new connection.

You can either extend org.springframework.jdbc.datasource.DelegatingDataSource and make your own custom wrapper by overriding getConnection methods, or you can use the existing UserCredentialsDataSourceAdapter that allows, among other things, to change the scheme of the underlying data source. Check the example below.

@RunWith(SpringRunner.class)
@DataJpaTest
@AutoConfigureEmbeddedDatabase(beanName = "commonDataSource")
public class DatabaseWithMultipleSchemasTest {

    @TestConfiguration // or @Configuration
    static class Config {

        @Bean
        @Primary
        public DataSource xDataSource(DataSource commonDataSource) {
            UserCredentialsDataSourceAdapter adapter = new UserCredentialsDataSourceAdapter();
            adapter.setTargetDataSource(commonDataSource);
            adapter.setSchema("schemaX");
            return adapter;
        }

        @Bean
        public DataSource yDataSource(DataSource commonDataSource) {
            UserCredentialsDataSourceAdapter adapter = new UserCredentialsDataSourceAdapter();
            adapter.setTargetDataSource(commonDataSource);
            adapter.setSchema("schemaY");
            return adapter;
        }

        @Bean
        public DataSource zDataSource(DataSource commonDataSource) {
            UserCredentialsDataSourceAdapter adapter = new UserCredentialsDataSourceAdapter();
            adapter.setTargetDataSource(commonDataSource);
            adapter.setSchema("schemaZ");
            return adapter;
        }
    }

    @Autowired
    @Qualifier("xDataSource")
    private DataSource xDataSource;

    @Autowired
    @Qualifier("yDataSource")
    private DataSource yDataSource;

    @Autowired
    @Qualifier("zDataSource")
    private DataSource zDataSource;

    // class body...
}

@tomix26
Copy link
Collaborator

tomix26 commented Apr 8, 2023

In the future, I will try to come up with some easier way to handle these cases.

@tomix26 tomix26 added the type: enhancement A general enhancement label Apr 8, 2023
@tomix26 tomix26 added the status: waiting-for-feedback We need additional information before we can continue label Apr 8, 2023
@mcherb
Copy link
Author

mcherb commented Apr 13, 2023

@tomix26 thank you for your quick replay. I let you know if your solution works for me. I didn't try it yet

@mcherb
Copy link
Author

mcherb commented Apr 25, 2023

Hello @tomix26 ,

Your solution with the commonDataSource works fine. But yes, it requires more configuration. If we have another simple solution it will be great.

Thanks again

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

2 participants