Play Framework JDBC support library providing database access, connection pooling, and database configuration management for Play applications.
—
Type-safe configuration system supporting multiple databases, JNDI, environment-specific settings, and various database connection formats.
Type-safe holder for database configuration parameters.
case class DatabaseConfig(
driver: Option[String],
url: Option[String],
username: Option[String],
password: Option[String],
jndiName: Option[String]
)Usage Examples:
import play.api.db.DatabaseConfig
// Minimal configuration
val basicConfig = DatabaseConfig(
driver = Some("org.h2.Driver"),
url = Some("jdbc:h2:mem:test"),
username = None,
password = None,
jndiName = None
)
// Full configuration
val prodConfig = DatabaseConfig(
driver = Some("org.postgresql.Driver"),
url = Some("jdbc:postgresql://db.example.com:5432/production"),
username = Some("app_user"),
password = Some("secure_password"),
jndiName = Some("java:comp/env/jdbc/ProductionDB")
)
// JNDI-only configuration
val jndiConfig = DatabaseConfig(
driver = None,
url = None,
username = None,
password = None,
jndiName = Some("java:comp/env/jdbc/ExternalDB")
)Factory method for creating DatabaseConfig from Play Configuration.
object DatabaseConfig {
def fromConfig(config: Configuration, environment: Environment): DatabaseConfig
}Usage Examples:
import play.api.db.DatabaseConfig
import play.api.{Configuration, Environment}
import com.typesafe.config.ConfigFactory
val configData = ConfigFactory.parseString("""
driver = "org.postgresql.Driver"
url = "postgres://user:pass@localhost/mydb"
username = "override_user"
logSql = true
""")
val config = Configuration(configData)
val environment = Environment.simple()
val dbConfig = DatabaseConfig.fromConfig(config, environment)
// Results in:
// DatabaseConfig(
// driver = Some("org.postgresql.Driver"),
// url = Some("jdbc:postgresql://localhost/mydb"),
// username = Some("override_user"), // overrides URL credential
// password = Some("pass"), // extracted from URL
// jndiName = None
// )Primary configuration through application.conf:
# Single database configuration
db.default {
driver = "org.postgresql.Driver"
url = "jdbc:postgresql://localhost/myapp"
username = "dbuser"
password = "dbpass"
# Connection pool settings
hikaricp {
minimumIdle = 5
maximumPoolSize = 20
}
# Optional settings
jndiName = "java:comp/env/jdbc/MyAppDB"
logSql = false
}
# Multiple database configuration
db {
users {
driver = "org.postgresql.Driver"
url = "jdbc:postgresql://users-db:5432/users"
username = ${DB_USER}
password = ${DB_PASS}
}
cache {
driver = "org.h2.Driver"
url = "jdbc:h2:mem:cache;DB_CLOSE_DELAY=-1"
}
analytics {
driver = "org.postgresql.Driver"
url = "jdbc:postgresql://analytics:5432/warehouse"
username = "analyst"
password = "readonly"
hikaricp.readOnly = true
}
}Support for environment variable substitution:
db.default {
driver = "org.postgresql.Driver"
url = ${DATABASE_URL}
username = ${DB_USERNAME}
password = ${DB_PASSWORD}
hikaricp {
maximumPoolSize = ${?DB_POOL_SIZE} # Optional with default fallback
}
}Configuration can be overridden via system properties:
# Command line system properties
java -Ddb.default.url="jdbc:postgresql://prod-db/myapp" \
-Ddb.default.username="prod_user" \
-Ddb.default.password="prod_pass" \
-jar myapp.jardb.default {
driver = "org.postgresql.Driver"
url = "jdbc:postgresql://localhost:5432/myapp?ssl=true&sslmode=require"
username = "user"
password = "pass"
}PostgreSQL Shortcut:
db.default {
url = "postgres://user:pass@localhost:5432/myapp"
# Automatically converts to: jdbc:postgresql://localhost:5432/myapp
# Credentials automatically extracted
}MySQL Shortcut:
db.default {
url = "mysql://user:pass@localhost:3306/myapp"
# Automatically converts to: jdbc:mysql://localhost:3306/myapp?useUnicode=yes&characterEncoding=UTF-8&connectionCollation=utf8_general_ci
# Credentials automatically extracted
}H2 Development Enhancement:
db.default {
url = "jdbc:h2:mem:testdb"
# In development mode, automatically becomes: jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1
}Credentials can be specified in multiple ways with precedence order:
username/password configuration (highest precedence)db.default {
url = "postgres://url_user:url_pass@localhost/myapp"
username = "config_user" # This overrides URL credential
password = "config_pass" # This overrides URL credential
# Final result: config_user/config_pass is used
}Configure database to use existing JNDI data source:
db.default {
jndiName = "java:comp/env/jdbc/MyAppDB"
# No driver, url, username, password needed
}Bind created data source to JNDI name:
db.default {
driver = "org.postgresql.Driver"
url = "jdbc:postgresql://localhost/myapp"
username = "user"
password = "pass"
jndiName = "java:comp/env/jdbc/MyAppDB" # Binds data source to this JNDI name
}# conf/application.conf
db.default {
driver = "org.h2.Driver"
url = "jdbc:h2:mem:devdb;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false"
username = "sa"
password = ""
hikaricp {
minimumIdle = 1
maximumPoolSize = 5
}
logSql = true # Enable SQL logging in development
}# conf/application.prod.conf
include "application.conf"
db.default {
driver = "org.postgresql.Driver"
url = ${DATABASE_URL}
username = ${DB_USERNAME}
password = ${DB_PASSWORD}
hikaricp {
minimumIdle = 10
maximumPoolSize = 30
connectionTimeout = 30 seconds
idleTimeout = 10 minutes
maxLifetime = 30 minutes
leakDetectionThreshold = 60 seconds
}
logSql = false # Disable SQL logging in production
}# conf/application.test.conf
include "application.conf"
db.default {
driver = "org.h2.Driver"
url = "jdbc:h2:mem:testdb;MODE=PostgreSQL;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false"
username = "sa"
password = ""
}Common configuration errors and solutions:
// Missing driver
db.default {
url = "jdbc:postgresql://localhost/myapp"
# Error: Driver not specified and cannot be inferred
}
// Invalid URL format
db.default {
driver = "org.postgresql.Driver"
url = "invalid-url"
# Error: Invalid JDBC URL format
}
// Conflicting JNDI and direct configuration
db.default {
driver = "org.postgresql.Driver"
url = "jdbc:postgresql://localhost/myapp"
jndiName = "java:comp/env/jdbc/DB"
# Warning: Both direct config and JNDI specified, JNDI takes precedence
}Support for legacy configuration property names:
db.default {
# Legacy property names (deprecated but supported)
user = "dbuser" # Use 'username' instead
pass = "dbpass" # Use 'password' instead
# Current property names (preferred)
username = "dbuser" # Overrides 'user' if both specified
password = "dbpass" # Overrides 'pass' if both specified
}# Old format (still supported)
db.default.driver = "org.postgresql.Driver"
db.default.url = "jdbc:postgresql://localhost/myapp"
db.default.user = "dbuser"
db.default.pass = "dbpass"
# New format (recommended)
db.default {
driver = "org.postgresql.Driver"
url = "jdbc:postgresql://localhost/myapp"
username = "dbuser"
password = "dbpass"
}# Good: Use environment variables
db.default {
username = ${DB_USERNAME}
password = ${DB_PASSWORD}
}
# Bad: Hardcoded credentials
db.default {
username = "hardcoded_user"
password = "hardcoded_pass"
}db.default {
# Size pool appropriately for workload
hikaricp {
minimumIdle = 5
maximumPoolSize = 20 # Formula: (core_count * 2) + disk_count
# Configure timeouts appropriately
connectionTimeout = 30 seconds
idleTimeout = 10 minutes
maxLifetime = 30 minutes
}
}db.default {
hikaricp {
# Enable monitoring in production
registerMbeans = true
leakDetectionThreshold = 60 seconds
}
# Enable SQL logging in development only
logSql = ${?ENABLE_SQL_LOGGING}
}Install with Tessl CLI
npx tessl i tessl/maven-com-typesafe-play--play-jdbc-2-11