0
# Database Configuration
1
2
Type-safe configuration system supporting multiple databases, JNDI, environment-specific settings, and various database connection formats.
3
4
## Capabilities
5
6
### DatabaseConfig Case Class
7
8
Type-safe holder for database configuration parameters.
9
10
```scala { .api }
11
case class DatabaseConfig(
12
driver: Option[String],
13
url: Option[String],
14
username: Option[String],
15
password: Option[String],
16
jndiName: Option[String]
17
)
18
```
19
20
**Usage Examples:**
21
22
```scala
23
import play.api.db.DatabaseConfig
24
25
// Minimal configuration
26
val basicConfig = DatabaseConfig(
27
driver = Some("org.h2.Driver"),
28
url = Some("jdbc:h2:mem:test"),
29
username = None,
30
password = None,
31
jndiName = None
32
)
33
34
// Full configuration
35
val prodConfig = DatabaseConfig(
36
driver = Some("org.postgresql.Driver"),
37
url = Some("jdbc:postgresql://db.example.com:5432/production"),
38
username = Some("app_user"),
39
password = Some("secure_password"),
40
jndiName = Some("java:comp/env/jdbc/ProductionDB")
41
)
42
43
// JNDI-only configuration
44
val jndiConfig = DatabaseConfig(
45
driver = None,
46
url = None,
47
username = None,
48
password = None,
49
jndiName = Some("java:comp/env/jdbc/ExternalDB")
50
)
51
```
52
53
### DatabaseConfig Factory Method
54
55
Factory method for creating DatabaseConfig from Play Configuration.
56
57
```scala { .api }
58
object DatabaseConfig {
59
def fromConfig(config: Configuration, environment: Environment): DatabaseConfig
60
}
61
```
62
63
**Usage Examples:**
64
65
```scala
66
import play.api.db.DatabaseConfig
67
import play.api.{Configuration, Environment}
68
import com.typesafe.config.ConfigFactory
69
70
val configData = ConfigFactory.parseString("""
71
driver = "org.postgresql.Driver"
72
url = "postgres://user:pass@localhost/mydb"
73
username = "override_user"
74
logSql = true
75
""")
76
77
val config = Configuration(configData)
78
val environment = Environment.simple()
79
80
val dbConfig = DatabaseConfig.fromConfig(config, environment)
81
// Results in:
82
// DatabaseConfig(
83
// driver = Some("org.postgresql.Driver"),
84
// url = Some("jdbc:postgresql://localhost/mydb"),
85
// username = Some("override_user"), // overrides URL credential
86
// password = Some("pass"), // extracted from URL
87
// jndiName = None
88
// )
89
```
90
91
## Configuration Sources
92
93
### Application Configuration
94
95
Primary configuration through `application.conf`:
96
97
```hocon
98
# Single database configuration
99
db.default {
100
driver = "org.postgresql.Driver"
101
url = "jdbc:postgresql://localhost/myapp"
102
username = "dbuser"
103
password = "dbpass"
104
105
# Connection pool settings
106
hikaricp {
107
minimumIdle = 5
108
maximumPoolSize = 20
109
}
110
111
# Optional settings
112
jndiName = "java:comp/env/jdbc/MyAppDB"
113
logSql = false
114
}
115
116
# Multiple database configuration
117
db {
118
users {
119
driver = "org.postgresql.Driver"
120
url = "jdbc:postgresql://users-db:5432/users"
121
username = ${DB_USER}
122
password = ${DB_PASS}
123
}
124
125
cache {
126
driver = "org.h2.Driver"
127
url = "jdbc:h2:mem:cache;DB_CLOSE_DELAY=-1"
128
}
129
130
analytics {
131
driver = "org.postgresql.Driver"
132
url = "jdbc:postgresql://analytics:5432/warehouse"
133
username = "analyst"
134
password = "readonly"
135
hikaricp.readOnly = true
136
}
137
}
138
```
139
140
### Environment Variables
141
142
Support for environment variable substitution:
143
144
```hocon
145
db.default {
146
driver = "org.postgresql.Driver"
147
url = ${DATABASE_URL}
148
username = ${DB_USERNAME}
149
password = ${DB_PASSWORD}
150
151
hikaricp {
152
maximumPoolSize = ${?DB_POOL_SIZE} # Optional with default fallback
153
}
154
}
155
```
156
157
### System Properties
158
159
Configuration can be overridden via system properties:
160
161
```bash
162
# Command line system properties
163
java -Ddb.default.url="jdbc:postgresql://prod-db/myapp" \
164
-Ddb.default.username="prod_user" \
165
-Ddb.default.password="prod_pass" \
166
-jar myapp.jar
167
```
168
169
## URL Formats and Shortcuts
170
171
### Standard JDBC URLs
172
173
```hocon
174
db.default {
175
driver = "org.postgresql.Driver"
176
url = "jdbc:postgresql://localhost:5432/myapp?ssl=true&sslmode=require"
177
username = "user"
178
password = "pass"
179
}
180
```
181
182
### Shortcut URL Formats
183
184
**PostgreSQL Shortcut:**
185
```hocon
186
db.default {
187
url = "postgres://user:pass@localhost:5432/myapp"
188
# Automatically converts to: jdbc:postgresql://localhost:5432/myapp
189
# Credentials automatically extracted
190
}
191
```
192
193
**MySQL Shortcut:**
194
```hocon
195
db.default {
196
url = "mysql://user:pass@localhost:3306/myapp"
197
# Automatically converts to: jdbc:mysql://localhost:3306/myapp?useUnicode=yes&characterEncoding=UTF-8&connectionCollation=utf8_general_ci
198
# Credentials automatically extracted
199
}
200
```
201
202
**H2 Development Enhancement:**
203
```hocon
204
db.default {
205
url = "jdbc:h2:mem:testdb"
206
# In development mode, automatically becomes: jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1
207
}
208
```
209
210
### Credential Handling
211
212
Credentials can be specified in multiple ways with precedence order:
213
214
1. Explicit `username`/`password` configuration (highest precedence)
215
2. URL-embedded credentials
216
3. Environment variables
217
4. System properties
218
219
```hocon
220
db.default {
221
url = "postgres://url_user:url_pass@localhost/myapp"
222
username = "config_user" # This overrides URL credential
223
password = "config_pass" # This overrides URL credential
224
# Final result: config_user/config_pass is used
225
}
226
```
227
228
## JNDI Configuration
229
230
### JNDI Data Source
231
232
Configure database to use existing JNDI data source:
233
234
```hocon
235
db.default {
236
jndiName = "java:comp/env/jdbc/MyAppDB"
237
# No driver, url, username, password needed
238
}
239
```
240
241
### JNDI Binding
242
243
Bind created data source to JNDI name:
244
245
```hocon
246
db.default {
247
driver = "org.postgresql.Driver"
248
url = "jdbc:postgresql://localhost/myapp"
249
username = "user"
250
password = "pass"
251
jndiName = "java:comp/env/jdbc/MyAppDB" # Binds data source to this JNDI name
252
}
253
```
254
255
## Environment-Specific Configuration
256
257
### Development Configuration
258
259
```hocon
260
# conf/application.conf
261
db.default {
262
driver = "org.h2.Driver"
263
url = "jdbc:h2:mem:devdb;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false"
264
username = "sa"
265
password = ""
266
267
hikaricp {
268
minimumIdle = 1
269
maximumPoolSize = 5
270
}
271
272
logSql = true # Enable SQL logging in development
273
}
274
```
275
276
### Production Configuration
277
278
```hocon
279
# conf/application.prod.conf
280
include "application.conf"
281
282
db.default {
283
driver = "org.postgresql.Driver"
284
url = ${DATABASE_URL}
285
username = ${DB_USERNAME}
286
password = ${DB_PASSWORD}
287
288
hikaricp {
289
minimumIdle = 10
290
maximumPoolSize = 30
291
connectionTimeout = 30 seconds
292
idleTimeout = 10 minutes
293
maxLifetime = 30 minutes
294
leakDetectionThreshold = 60 seconds
295
}
296
297
logSql = false # Disable SQL logging in production
298
}
299
```
300
301
### Test Configuration
302
303
```hocon
304
# conf/application.test.conf
305
include "application.conf"
306
307
db.default {
308
driver = "org.h2.Driver"
309
url = "jdbc:h2:mem:testdb;MODE=PostgreSQL;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false"
310
username = "sa"
311
password = ""
312
}
313
```
314
315
## Configuration Validation
316
317
### Required vs Optional Fields
318
319
- **driver**: Required unless using JNDI
320
- **url**: Required unless using JNDI
321
- **username**: Optional (can be embedded in URL)
322
- **password**: Optional (can be embedded in URL)
323
- **jndiName**: Optional (for JNDI binding or lookup)
324
325
### Configuration Errors
326
327
Common configuration errors and solutions:
328
329
```scala
330
// Missing driver
331
db.default {
332
url = "jdbc:postgresql://localhost/myapp"
333
# Error: Driver not specified and cannot be inferred
334
}
335
336
// Invalid URL format
337
db.default {
338
driver = "org.postgresql.Driver"
339
url = "invalid-url"
340
# Error: Invalid JDBC URL format
341
}
342
343
// Conflicting JNDI and direct configuration
344
db.default {
345
driver = "org.postgresql.Driver"
346
url = "jdbc:postgresql://localhost/myapp"
347
jndiName = "java:comp/env/jdbc/DB"
348
# Warning: Both direct config and JNDI specified, JNDI takes precedence
349
}
350
```
351
352
## Legacy Configuration Support
353
354
### Deprecated Properties
355
356
Support for legacy configuration property names:
357
358
```hocon
359
db.default {
360
# Legacy property names (deprecated but supported)
361
user = "dbuser" # Use 'username' instead
362
pass = "dbpass" # Use 'password' instead
363
364
# Current property names (preferred)
365
username = "dbuser" # Overrides 'user' if both specified
366
password = "dbpass" # Overrides 'pass' if both specified
367
}
368
```
369
370
### Migration Guide
371
372
```hocon
373
# Old format (still supported)
374
db.default.driver = "org.postgresql.Driver"
375
db.default.url = "jdbc:postgresql://localhost/myapp"
376
db.default.user = "dbuser"
377
db.default.pass = "dbpass"
378
379
# New format (recommended)
380
db.default {
381
driver = "org.postgresql.Driver"
382
url = "jdbc:postgresql://localhost/myapp"
383
username = "dbuser"
384
password = "dbpass"
385
}
386
```
387
388
## Configuration Best Practices
389
390
### Security
391
392
- Never commit passwords to version control
393
- Use environment variables for sensitive data
394
- Consider using secret management systems
395
- Encrypt configuration files in production
396
397
```hocon
398
# Good: Use environment variables
399
db.default {
400
username = ${DB_USERNAME}
401
password = ${DB_PASSWORD}
402
}
403
404
# Bad: Hardcoded credentials
405
db.default {
406
username = "hardcoded_user"
407
password = "hardcoded_pass"
408
}
409
```
410
411
### Performance
412
413
```hocon
414
db.default {
415
# Size pool appropriately for workload
416
hikaricp {
417
minimumIdle = 5
418
maximumPoolSize = 20 # Formula: (core_count * 2) + disk_count
419
420
# Configure timeouts appropriately
421
connectionTimeout = 30 seconds
422
idleTimeout = 10 minutes
423
maxLifetime = 30 minutes
424
}
425
}
426
```
427
428
### Monitoring
429
430
```hocon
431
db.default {
432
hikaricp {
433
# Enable monitoring in production
434
registerMbeans = true
435
leakDetectionThreshold = 60 seconds
436
}
437
438
# Enable SQL logging in development only
439
logSql = ${?ENABLE_SQL_LOGGING}
440
}
441
```