quarkiverse / quarkus-mybatis

Quarkus MyBatis Extension
Apache License 2.0
89 stars 33 forks source link

Unable to use databaseIdProvider #468

Closed p91paul closed 2 weeks ago

p91paul commented 2 weeks ago

I created the following mybatis-config.xml

<!DOCTYPE configuration
    PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="quarkus">
        <environment id="quarkus">
            <transactionManager type="JDBC"/>
            <dataSource type="QUARKUS"/>
        </environment>
    </environments>
    <databaseIdProvider type="DB_VENDOR">
        <property name="H2" value="h2"/>
        <property name="Oracle" value="oracle"/>
    </databaseIdProvider>
</configuration>

That configuration is read from https://github.com/quarkiverse/quarkus-mybatis/blob/77f203db6e26787e43bbf7d0726b567a70034a56/mybatis/deployment/src/main/java/io/quarkiverse/mybatis/deployment/MyBatisProcessor.java#L246

I'm not much of an expert in quarkus, but if I recollected information correctly @Record(ExecutionTime.STATIC_INIT) means that this action is executed at compile/build time, and not at runtime. This breaks the databaseIdProvider config, which by default opens a connection to the database, checks the connection metadata and determines the running database. Only after that mybatis can actually parse the mappers xml files, and resolve the correct query based on the databaseId.

See

I do not know if this is fixable with an option to create the session factory at runtime, and to do so only after the agroal extension did her work and created the actual datasource.

As an alternative, for my use case it would be enough for me to have a way to configure the databaseId at compile time without using a provider, e.g. to put something like this in application.properties:

xxxx.xxxx.databaseId=oracle
%test.xxxx.xxxx.databaseId=h2

This would be even better for me, because I do not need xml config at all (I only tried to use it to specify the databaseId provider)

zhfeng commented 2 weeks ago

@p91paul

I'm not much of an expert in quarkus, but if I recollected information correctly @Record(ExecutionTime.STATIC_INIT) means that this action is executed at compile/build time, and not at runtime.

Yeah, but it only impacts the native mode. Did you try to alter it to @Record(ExecutionTime.RUNTIME_INIT) to see if it works?

Can you provide a simple test for databaseId and it will be helpful when we consider the solution?

zhfeng commented 2 weeks ago

Basicly, I'm think to have our implementation of DatabaseIdProvider to provide the databaseId based on the config from application.properties

p91paul commented 2 weeks ago

I've built a reproducer project; you'll see it fails to start both during tests and normal run in dev mode, because it will try to resolve databaseId before the agroal data source is created. I believe this is a side effect of this being a builditem (even without native compilation, these are executed before the application actually starts, are they not?)

demo-mybatis-quarkus-databaseid.zip

The example is based on what mybatis documentation suggests you should be doing, which is more flexible because it's a runtime check; but as stated earlier, having a DatabaseIdProvider that reads from application.properties would be good enough for me!

zhfeng commented 2 weeks ago

Thanks @p91paul - I will check your reproducer asap.

zhfeng commented 1 week ago

@p91paul I just release 2.2.4 to include this fix.