Working setup plus one small application per way of getting it wrong (no @Primary, @Primary only, url vs jdbc-url, wrong repository package, Flyway auto-configuration), plain vs named @Transactional, and ChainedTransactionManager with a failing commit. Transcripts are written by the tests. Co-Authored-By: Claude Sonnet 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Uu7q8vPeREyT4218EJPzz1
3.8 KiB
3.8 KiB
multi-datasource
Companion project for the article Multiple DataSources in Spring Boot 4 with Spring Data JPA on ankurm.com.
Two H2 databases (customers and orders), each with its own DataSource, Flyway, EntityManagerFactory,
transaction manager and repository scan; plus one small application per way of getting that wrong.
Every console block quoted in the article came out of output/. Transcripts 01-09 are written by the test
suite (so a claim that stops being true turns the build red); 10-12 are read out of jars and javac by
scripts/capture-facts.sh.
There is deliberately no docs/ folder: the deeper material lives in collapsible "going deeper"
sections inside the article itself, next to the paragraph each one extends.
Versions
| Spring Boot | 4.1.1 |
| Spring Framework | 7.0.9 |
| Spring Data JPA / Commons | 4.1.1 |
| Hibernate ORM | 7.4.5.Final |
| Flyway | 12.4.0 |
| JDK | 25 (Temurin 25.0.4.1+1) |
| Maven | 3.9 |
| H2 | 2.4.240 (the version Boot 4.1.1 manages) |
Quickstart
export JAVA_HOME=/path/to/jdk-25
mvn test # runs every scenario and rewrites output/01-09
./scripts/run-all.sh # everything, including 10-12
Source layout
| Path | What it holds |
|---|---|
customers/ |
Customer, CustomerRepository and CustomersDbConfig: the @Primary database |
orders/ |
PurchaseOrder, OrderRepository and OrdersDbConfig: the second database |
service/PlacementService |
writes to both databases, then optionally throws; plain and named @Transactional |
MultiDsApp |
scans only the three packages above |
traps/nodefault |
two DataSource beans, none @Primary |
traps/primaryonly |
one @Primary DataSource, Boot's own JPA setup: it starts and uses the wrong database |
traps/jdbcurl |
@ConfigurationProperties bound straight onto a pool with a url key |
traps/builderdefaults |
what a hand-built EntityManagerFactory still gets from Spring Boot |
traps/flywayauto |
Spring Boot's Flyway auto-configuration with two databases |
traps/wrongpackage |
a repository whose entity is not in the factory it is scanned against |
src/test/.../chain/ |
ChainedTransactionManager, and a transaction manager whose commit fails |
src/main/resources/db/migration/{customers,orders}/ |
one Flyway location per database |
Index of captured output
| File | Written by | What it shows |
|---|---|---|
01-two-databases.txt |
TwoDatabasesTests |
pools, Flyway histories, what each factory manages, where each repository writes |
02-no-primary.txt |
TrapsTests |
two DataSource beans without @Primary |
03-primary-only-wrong-database.txt |
TrapsTests |
it starts, and both tables are in the customers database |
04-url-vs-jdbc-url.txt |
TrapsTests |
url does not bind onto a pool |
05-builder-defaults.txt |
TrapsTests |
naming strategy and ddl-auto on a hand-built factory |
06-flyway-auto-configuration.txt |
TrapsTests |
three ways Flyway auto-configuration meets two databases, and which database each one migrated |
07-wrong-package.txt |
TrapsTests |
Not a managed type |
08-which-transaction-manager.txt |
TwoDatabasesTests |
plain vs named @Transactional |
09-chained-transaction-manager.txt |
ChainedTests |
rollback, and commit failure in both list orders |
10-chained-transaction-manager-jar.txt |
capture-facts.sh |
ChainedTransactionManager is still shipped, and @Deprecated |
11-enable-jpa-repositories-not-repeatable.txt |
capture-facts.sh |
javac on two @EnableJpaRepositories on one class |
12-builder-packages.txt |
capture-facts.sh |
Builder.packages(Class...) derives a package name from each class |