spring-boothibernatespring-data-jpa

Spring Data JPA - @Query annotation with qualifier for the database it applies to


I'm using Spring boot with a native sequence query to get the next number in a sequence (it gets reset every year, so the auto-id field won't work).

How can I specify which database the query applies to?

@Query("select nextval('seq_item_number')", nativeQuery = true)

BEGIN EDIT

Editing for clarification - I do not want to connect to > 1 database at a time. I want to be able to deploy instance 1 and use Postgres, instance 2 and use MySQL, instance 3 and use MSSQL, etc...

Then, for native queries that are not ANSI supported, I want to have annotations like I can for MyBatis - one for each database and at runtime it will use the appropriate query. Here is an example (not valid code, but shows what I want to do):

@Queries[
@Query("select nextval('seq_item_number')", nativeQuery = true, dbVendor='postgresl'),
@Query("<some mysql query>", nativeQuery = true, dbVendor='mysql'),
@Query("<some mssql query>", nativeQuery = true, dbVendor='mssql')
]

Then, when my query is to be run, at runtime - Spring will pick the appropriate query based on the database that this instance is connected to.

END EDIT

I would like to specify the something like dbVendor = 'postgres' for one query, and dbVendor = 'mysql' for a different query so the repository method knows which native query to run based on my db vendor.

I've done this with MyBatis annotations before, can I do it with JPA?


Solution

  • I figured out the best way - create an interface and then create @Repository annotated beans the implement the interface, one for each database vendor.

    Then, when I deploy my app, I conditionally create the correct bean based on a profile.

    Something like:

    interface EntityNumberProvider {
        fun nextNumber(): Long
        fun resetNumberSequence(): Unit
    }
    
    @Repository
    @Profile("postgresql")
    class PostgresqlEntityNumberProvider(@Autowired entityManager: EntityManager)
          : EntityNumberProvider {
       // Postgres specific code
    }
    
    @Repository
    @Profile("mssql")
    class MSSQLEntityNumberProvider(@Autowired entityManager: EntityManager)
          : EntityNumberProvider {
       // MSSQL specific code
    }
    

    Then, set the appropriate profile as active when I deploy and all good...