Documentation

You are viewing the documentation for the 2.5.x release series. The latest stable release series is 3.0.x.

§Accessing an SQL database

§Configuring JDBC connection pools

Play provides a plugin for managing JDBC connection pools. You can configure as many databases as you need.

To enable the database plugin add javaJdbc in your build dependencies :

libraryDependencies += javaJdbc

Then you must configure a connection pool in the conf/application.conf file. By convention the default JDBC data source must be called default:

# Default database configuration
db.default.driver=org.h2.Driver
db.default.url="jdbc:h2:mem:play"

To configure several data sources:

# Orders database
db.orders.driver=org.h2.Driver
db.orders.url="jdbc:h2:mem:orders"

# Customers database
db.customers.driver=org.h2.Driver
db.customers.url="jdbc:h2:mem:customers"

If something isn’t properly configured, you will be notified directly in your browser:

§H2 database engine connection properties

# Default database configuration using H2 database engine in an in-memory mode
db.default.driver=org.h2.Driver
db.default.url="jdbc:h2:mem:play"
# Default database configuration using H2 database engine in a persistent mode
db.default.driver=org.h2.Driver
db.default.url="jdbc:h2:/path/to/db-file"

The details of the H2 database URLs are found from H2 Database Engine Cheat Sheet.

§SQLite database engine connection properties

# Default database configuration using SQLite database engine
db.default.driver=org.sqlite.JDBC
db.default.url="jdbc:sqlite:/path/to/db-file"

§PostgreSQL database engine connection properties

# Default database configuration using PostgreSQL database engine
db.default.driver=org.postgresql.Driver
db.default.url="jdbc:postgresql://database.example.com/playdb"

§MySQL database engine connection properties

# Default database configuration using MySQL database engine
# Connect to playdb as playdbuser
db.default.driver=com.mysql.jdbc.Driver
db.default.url="jdbc:mysql://localhost/playdb"
db.default.username=playdbuser
db.default.password="a strong password"

§Accessing the JDBC datasource

The play.db package provides access to the default datasource.

/*
 * Copyright (C) 2009-2016 Lightbend Inc. <http://www.lightbend.com>
 */
package javaguide.sql;

import javax.inject.Inject;

import play.mvc.*;
import play.db.*;

class JavaApplicationDatabase extends Controller {

    private Database db;

    @Inject
    public JavaApplicationDatabase(Database db) {
        this.db = db;
    }

    // ...
}

For a database other than the default:

/*
 * Copyright (C) 2009-2016 Lightbend Inc. <http://www.lightbend.com>
 */
package javaguide.sql;

import javax.inject.Inject;

import play.mvc.Controller;
import play.db.NamedDatabase;
import play.db.Database;

// inject "orders" database instead of "default"
class JavaNamedDatabase extends Controller {
    private Database db;

    @Inject
    public JavaNamedDatabase(@NamedDatabase("orders") Database db) {
        this.db = db;
    }

    // do whatever you need with the db
}

§Obtaining a JDBC connection

You can retrieve a JDBC connection the same way:

Connection connection = db.getConnection();

It is important to note that resulting Connections are not automatically disposed at the end of the request cycle. In other words, you are responsible for calling their close() method somewhere in your code so that they can be immediately returned to the pool.

§Exposing the datasource through JNDI

Some libraries expect to retrieve the Datasource reference from JNDI. You can expose any Play managed datasource via JDNI by adding this configuration in conf/application.conf:

db.default.driver=org.h2.Driver
db.default.url="jdbc:h2:mem:play"
db.default.jndiName=DefaultDS

§How to configure SQL log statement

Not all connection pools offer (out of the box) a way to log SQL statements. HikariCP, per instance, suggests that you use the log capacities of your database vendor. From HikariCP docs:

§Log Statement Text / Slow Query Logging

Like Statement caching, most major database vendors support statement logging through properties of their own driver. This includes Oracle, MySQL, Derby, MSSQL, and others. Some even support slow query logging. We consider this a “development-time” feature. For those few databases that do not support it, jdbcdslog-exp is a good option. Great stuff during development and pre-Production.

Because of that, Play uses jdbcdslog-exp to enable consistent SQL log statement support for supported pools. The SQL log statement can be configured by database, using logSql property:

# Default database configuration using PostgreSQL database engine
db.default.driver=org.postgresql.Driver
db.default.url="jdbc:postgresql://database.example.com/playdb"
db.default.logSql=true

After that, you can configure the jdbcdslog-exp log level as explained in their manual. Basically, you need to configure your root logger to INFO and then decide what jdbcdslog-exp will log (connections, statements and result sets). Here is an example using logback.xml to configure the logs:

<!--
  ~ Copyright (C) 2009-2016 Lightbend Inc. <https://www.lightbend.com>
  -->
<!-- The default logback configuration that Play uses if no other configuration is provided -->
<configuration>

  <conversionRule conversionWord="coloredLevel" converterClass="play.api.libs.logback.ColoredLevel" />

  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
     <file>${application.home:-.}/logs/application.log</file>
     <encoder>
       <pattern>%date [%level] from %logger in %thread - %message%n%xException</pattern>
     </encoder>
  </appender>

  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>%coloredLevel %logger{15} - %message%n%xException{10}</pattern>
    </encoder>
  </appender>

  <appender name="ASYNCFILE" class="ch.qos.logback.classic.AsyncAppender">
    <appender-ref ref="FILE" />
  </appender>

  <appender name="ASYNCSTDOUT" class="ch.qos.logback.classic.AsyncAppender">
    <appender-ref ref="STDOUT" />
  </appender>

  <logger name="play" level="INFO" />
  <logger name="application" level="DEBUG" />

  <logger name="org.jdbcdslog.ConnectionLogger" level="OFF"  /> <!-- Won' log connections -->
  <logger name="org.jdbcdslog.StatementLogger"  level="INFO" /> <!-- Will log all statements -->
  <logger name="org.jdbcdslog.ResultSetLogger"  level="OFF"  /> <!-- Won' log result sets -->

  <root level="WARN">
    <appender-ref ref="ASYNCFILE" />
    <appender-ref ref="ASYNCSTDOUT" />
  </root>
  
</configuration>

Warning: Keep in mind that this is intended to be used just in development environments and you should not configure it in production, since there is a performance degradation and it will pollute your logs.

§Configuring the JDBC Driver dependency

Other than for the h2 in-memory database, useful mostly in development mode, Play does not provide any database drivers. Consequently, to deploy in production you will have to add your database driver as an application dependency.

For example, if you use MySQL5, you need to add a dependency for the connector:

libraryDependencies += "mysql" % "mysql-connector-java" % "5.1.36"

§Selecting and configuring the connection pool

Out of the box, Play provides two database connection pool implementations, HikariCP and BoneCP. The default is HikariCP, but this can be changed by setting the play.db.pool property:

play.db.pool=bonecp

The full range of configuration options for connection pools can be found by inspecting the play.db.prototype property in Play’s JDBC reference.conf.

§Testing

For information on testing with databases, including how to setup in-memory databases and, see Testing With Databases.

§Enabling Play database evolutions

Read Evolutions to find out what Play database evolutions are useful for, and follow the instructions for using it.

Next: Integrating with JPA


Found an error in this documentation? The source code for this page can be found here. After reading the documentation guidelines, please feel free to contribute a pull request. Have questions or advice to share? Go to our community forums to start a conversation with the community.