Files
spring-boot-demo/multi-datasource/README.md
T
Claude e59ff029a1 Add multi-datasource module: two databases with per-database DataSource, Flyway, EntityManagerFactory and transaction manager on Boot 4.1
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
2026-09-24 09:38:27 +00:00

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