spring-boot-jpa
Spring Data JPA — MySQL and PostgreSQL
spring-boot-scaffold covers the basic entity/repository/service/controller shape and the default FetchType.LAZY convention. This skill goes one level deeper: the Hibernate/JPA behavior that actually differs between relational engines, and the configuration each engine needs to get right in production. It assumes MySQL or PostgreSQL as the target — for a document database, see spring-boot-mongodb; for hand-written SQL instead of an ORM, see spring-boot-jdbc.
Dialect selection — don't hand-set it
Hibernate auto-detects the SQL dialect from the JDBC connection metadata since the 6.x line. Note the generation jump across the Boot major version: Spring Boot 3.x ships Hibernate 6.x, but Spring Boot 4.x moved to Hibernate 7.x (7.4.x as of Boot 4.1.1) — don't assume 3.x-era Hibernate 6 release notes or CVE advisories apply unchanged to a 4.x project. spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect (or PostgreSQLDialect) is a leftover from pre-6.x Hibernate versions — flag it in review if seen; it's not wrong, just unnecessary, and it's an extra place to get out of sync if the project ever migrates versions.
ID generation — this is where MySQL and PostgreSQL genuinely diverge
| MySQL | PostgreSQL | |
|---|---|---|
| Native sequence support | No — MySQL has no CREATE SEQUENCE |
Yes — real SEQUENCE objects |
Recommended @GeneratedValue strategy |
GenerationType.IDENTITY (maps to AUTO_INCREMENT) |
GenerationType.SEQUENCE with an explicit @SequenceGenerator |
| JDBC batch inserts | Broken by IDENTITY (see below) unless rewriteBatchedStatements=true is set |
Works out of the box with SEQUENCE |
The batching gotcha, concretely: Hibernate needs the generated key back before it can hand the next row to the JDBC batch, so GenerationType.IDENTITY silently disables Hibernate's own JDBC batching regardless of hibernate.jdbc.batch_size — each insert becomes its own round trip. Two ways to actually get batched inserts on MySQL: