MySQL & PostgreSQL
MySQL Configuration
Add the MySQL JDBC driver in pom.xml:
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
Configuration in application.properties:
# MySQL
spring.datasource.url=jdbc:mysql://localhost:3306/myapp_db
spring.datasource.username=root
spring.datasource.password=secret123
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# Hibernate
spring.jpa.hibernate.ddl-auto=validate
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect
Create the database first:
CREATE DATABASE myapp_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
PostgreSQL Configuration
Add the PostgreSQL JDBC driver:
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
Configuration in application.properties:
# PostgreSQL
spring.datasource.url=jdbc:postgresql://localhost:5432/myapp_db
spring.datasource.username=postgres
spring.datasource.password=secret123
spring.datasource.driver-class-name=org.postgresql.Driver
# Hibernate
spring.jpa.hibernate.ddl-auto=validate
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
Create the database:
CREATE DATABASE myapp_db;
Connection Pool: HikariCP
Spring Boot uses HikariCP as the default connection pool. It's very fast and efficient:
# HikariCP Configuration
spring.datasource.hikari.maximum-pool-size=20
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.idle-timeout=30000
spring.datasource.hikari.max-lifetime=1800000
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.pool-name=MyAppHikariPool
| Property | Default | Description |
|---|---|---|
maximum-pool-size |
10 | Maximum active connections |
minimum-idle |
10 | Minimum idle connections |
idle-timeout |
600000 (10m) | Idle time before closing |
max-lifetime |
1800000 (30m) | Maximum connection lifetime |
connection-timeout |
30000 (30s) | Timeout when acquiring a connection |
Profile-Specific Configuration
Use profiles to separate configuration per environment:
# application-dev.properties (development)
spring.datasource.url=jdbc:h2:mem:devdb
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.show-sql=true
# application-staging.properties (staging)
spring.datasource.url=jdbc:mysql://staging-db:3306/myapp_db
spring.datasource.hikari.maximum-pool-size=10
spring.jpa.hibernate.ddl-auto=validate
# application-prod.properties (production)
spring.datasource.url=jdbc:postgresql://prod-db:5432/myapp_db
spring.datasource.hikari.maximum-pool-size=20
spring.jpa.hibernate.ddl-auto=validate
spring.jpa.show-sql=false
Activate a profile at runtime:
# Via command line
java -jar app.jar --spring.profiles.active=prod
# Via environment variable
export SPRING_PROFILES_ACTIVE=prod
Database Migration: Flyway
Flyway manages database schema changes in a versioned way:
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-mysql</artifactId>
</dependency>
# Flyway config
spring.flyway.enabled=true
spring.flyway.locations=classpath:db/migration
spring.flyway.baseline-on-migrate=true
Migration file structure:
src/main/resources/db/migration/
├── V1__create_users_table.sql
├── V2__add_email_index.sql
└── V3__create_orders_table.sql
-- V1__create_users_table.sql
CREATE TABLE users (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- V2__add_email_index.sql
CREATE INDEX idx_users_email ON users(email);
Database Migration: Liquibase
Another alternative is Liquibase, using XML/YAML/SQL:
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
</dependency>
# Liquibase config
spring.liquibase.change-log=classpath:db/changelog/db.changelog-master.xml
spring.liquibase.enabled=true
<!-- db/changelog/db.changelog-master.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog>
<include file="db/changelog/changes/001-create-users.xml"/>
<include file="db/changelog/changes/002-add-orders.xml"/>
</databaseChangeLog>
Flyway vs Liquibase Comparison
| Aspect | Flyway | Liquibase |
|---|---|---|
| File format | SQL | XML, YAML, SQL |
| Naming | V1__desc.sql |
Free (registered in the changelog) |
| Rollback | Manual (write reverse SQL) | Built-in rollback |
| Learning curve | Low | Moderate |
| Community | Large | Large |
MySQL vs PostgreSQL Comparison
| Aspect | MySQL | PostgreSQL |
|---|---|---|
| License | GPL / Commercial | PostgreSQL License |
| JSON Support | JSON type | JSONB (more powerful) |
| ACID | InnoDB | Full support |
| Extensions | Limited | Very many (PostGIS, etc.) |
| Concurrency | Good | Very good (MVCC) |
| Popularity | Very high | High |
Choose MySQL for simplicity or PostgreSQL for a more complete feature set. Both are excellent for production. In the next chapter, we'll learn about Testing in Spring Boot.