or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

connection-pooling.mddatabase-configuration.mddatabase-management.mddatabase-operations.mddependency-injection.mdindex.md

database-management.mddocs/

0

# Multi-Database Management

1

2

API for managing multiple database configurations in a single application, with named database support and lifecycle management.

3

4

## Capabilities

5

6

### DBApi Interface (Scala)

7

8

Primary interface for managing multiple databases in Scala.

9

10

```scala { .api }

11

trait DBApi {

12

/** All configured databases */

13

def databases(): Seq[Database]

14

/** Get database with given configuration name */

15

def database(name: String): Database

16

/** Shutdown all databases, releasing resources */

17

def shutdown(): Unit

18

}

19

```

20

21

**Usage Examples:**

22

23

```scala

24

import play.api.db._

25

import javax.inject.Inject

26

27

class MultiDbController @Inject()(dbApi: DBApi) {

28

// Access specific databases by name

29

def getUserData(userId: Long) = {

30

val userDb = dbApi.database("users")

31

val profileDb = dbApi.database("profiles")

32

33

userDb.withConnection { implicit conn =>

34

// Query user data

35

val stmt = conn.prepareStatement("SELECT name FROM users WHERE id = ?")

36

stmt.setLong(1, userId)

37

val rs = stmt.executeQuery()

38

// ... process results

39

}

40

}

41

42

// Iterate over all databases

43

def performMaintenance() = {

44

dbApi.databases().foreach { db =>

45

println(s"Performing maintenance on database: ${db.name}")

46

db.withConnection { implicit conn =>

47

// Maintenance operations

48

conn.prepareStatement("ANALYZE").execute()

49

}

50

}

51

}

52

53

// Graceful shutdown

54

def cleanup() = {

55

dbApi.shutdown()

56

}

57

}

58

```

59

60

### DBApi Interface (Java)

61

62

Primary interface for managing multiple databases in Java.

63

64

```java { .api }

65

public interface DBApi {

66

/** @return all configured databases */

67

List<Database> getDatabases();

68

/** Get database with given configuration name */

69

Database getDatabase(String name);

70

/** Shutdown all databases, releasing resources */

71

void shutdown();

72

}

73

```

74

75

**Usage Examples:**

76

77

```java

78

import play.db.*;

79

import javax.inject.Inject;

80

import java.util.List;

81

82

public class MultiDbController {

83

private final DBApi dbApi;

84

85

@Inject

86

public MultiDbController(DBApi dbApi) {

87

this.dbApi = dbApi;

88

}

89

90

// Access specific databases by name

91

public void processUserData(long userId) {

92

Database userDb = dbApi.getDatabase("users");

93

Database logDb = dbApi.getDatabase("logs");

94

95

userDb.withConnection(connection -> {

96

PreparedStatement stmt = connection.prepareStatement("SELECT email FROM users WHERE id = ?");

97

stmt.setLong(1, userId);

98

ResultSet rs = stmt.executeQuery();

99

// ... process results

100

});

101

102

logDb.withConnection(connection -> {

103

PreparedStatement stmt = connection.prepareStatement("INSERT INTO access_log (user_id, timestamp) VALUES (?, ?)");

104

stmt.setLong(1, userId);

105

stmt.setTimestamp(2, new Timestamp(System.currentTimeMillis()));

106

stmt.executeUpdate();

107

});

108

}

109

110

// Iterate over all databases

111

public void performHealthCheck() {

112

List<Database> databases = dbApi.getDatabases();

113

for (Database db : databases) {

114

try {

115

db.withConnection(connection -> {

116

PreparedStatement stmt = connection.prepareStatement("SELECT 1");

117

stmt.executeQuery();

118

});

119

System.out.println("Database " + db.getName() + " is healthy");

120

} catch (Exception e) {

121

System.err.println("Database " + db.getName() + " failed health check: " + e.getMessage());

122

}

123

}

124

}

125

}

126

```

127

128

### DefaultDBApi Implementation

129

130

Default implementation of the DBApi interface.

131

132

```scala { .api }

133

class DefaultDBApi(

134

configuration: Map[String, Config],

135

defaultConnectionPool: ConnectionPool = new HikariCPConnectionPool(Environment.simple()),

136

environment: Environment = Environment.simple(),

137

injector: Injector = NewInstanceInjector

138

) extends DBApi {

139

/** Try to initialize all the configured databases */

140

def initialize(logInitialization: Boolean): Unit

141

/** @deprecated Use initialize instead */

142

@deprecated("Use initialize instead, which does not try to connect to the database", "2.7.0")

143

def connect(logConnection: Boolean = false): Unit

144

}

145

```

146

147

**Usage Examples:**

148

149

```scala

150

import play.api.db._

151

import play.api.{Configuration, Environment}

152

import com.typesafe.config.ConfigFactory

153

154

// Create DBApi manually for testing

155

val config = Map(

156

"default" -> ConfigFactory.parseString("""

157

driver = "org.h2.Driver"

158

url = "jdbc:h2:mem:test"

159

"""),

160

"cache" -> ConfigFactory.parseString("""

161

driver = "org.h2.Driver"

162

url = "jdbc:h2:mem:cache"

163

""")

164

)

165

166

val dbApi = new DefaultDBApi(config)

167

dbApi.initialize(logInitialization = true)

168

169

try {

170

val defaultDb = dbApi.database("default")

171

val cacheDb = dbApi.database("cache")

172

// Use databases...

173

} finally {

174

dbApi.shutdown()

175

}

176

```

177

178

### Named Database Injection

179

180

Support for injecting specific databases by name using dependency injection.

181

182

```java { .api }

183

/** Qualifier annotation for dependency injection of named databases */

184

@Qualifier

185

@Retention(RetentionPolicy.RUNTIME)

186

public @interface NamedDatabase {

187

String value();

188

}

189

190

/** Implementation class for NamedDatabase annotation */

191

public class NamedDatabaseImpl implements NamedDatabase, Serializable {

192

public NamedDatabaseImpl(String value);

193

public String value();

194

}

195

```

196

197

**Usage Examples:**

198

199

```java

200

import play.db.*;

201

import javax.inject.Inject;

202

203

public class UserService {

204

private final Database userDb;

205

private final Database sessionDb;

206

207

@Inject

208

public UserService(

209

@NamedDatabase("users") Database userDb,

210

@NamedDatabase("sessions") Database sessionDb

211

) {

212

this.userDb = userDb;

213

this.sessionDb = sessionDb;

214

}

215

216

public void authenticateUser(String username, String password) {

217

// Use userDb for user lookup

218

Optional<User> user = userDb.withConnection(connection -> {

219

// User authentication logic

220

return findUser(username, password, connection);

221

});

222

223

if (user.isPresent()) {

224

// Use sessionDb for session management

225

sessionDb.withConnection(connection -> {

226

PreparedStatement stmt = connection.prepareStatement(

227

"INSERT INTO sessions (user_id, session_token, created_at) VALUES (?, ?, ?)"

228

);

229

stmt.setLong(1, user.get().getId());

230

stmt.setString(2, generateSessionToken());

231

stmt.setTimestamp(3, new Timestamp(System.currentTimeMillis()));

232

stmt.executeUpdate();

233

});

234

}

235

}

236

}

237

```

238

239

### Package Object Type Alias

240

241

Type alias for compatibility between Scala and Java APIs.

242

243

```scala { .api }

244

package object db {

245

type NamedDatabase = play.db.NamedDatabase

246

}

247

```

248

249

## Configuration

250

251

Multiple databases are configured in `application.conf`:

252

253

```hocon

254

# Database configuration key (default: "db")

255

play.db.config = "db"

256

257

# Default database name (default: "default")

258

play.db.default = "default"

259

260

# Multiple database configurations

261

db {

262

default {

263

driver = "org.postgresql.Driver"

264

url = "jdbc:postgresql://localhost/myapp"

265

username = "dbuser"

266

password = "dbpass"

267

}

268

269

cache {

270

driver = "org.h2.Driver"

271

url = "jdbc:h2:mem:cache"

272

}

273

274

analytics {

275

driver = "org.postgresql.Driver"

276

url = "jdbc:postgresql://analytics-server/warehouse"

277

username = "analyst"

278

password = "secret"

279

pool = "hikaricp"

280

}

281

}

282

```

283

284

## Error Handling

285

286

- **IllegalArgumentException**: Thrown when requesting a database that doesn't exist

287

- **Configuration errors**: Thrown during initialization for invalid database configurations

288

- **Connection errors**: Thrown during database initialization if connections cannot be established

289

290

## Lifecycle Management

291

292

- **Initialization**: Call `initialize()` to set up all configured databases

293

- **Shutdown**: Call `shutdown()` to gracefully close all database connections and connection pools

294

- **Automatic lifecycle**: When using Play's dependency injection, lifecycle is managed automatically through `ApplicationLifecycle`