This document covers obtaining JDBC connection information and creating database connections for testing with MySQL containers.
Connection Information Methods:
getJdbcUrl(): String - Returns complete JDBC URL with host, port, database, and parametersgetDriverClassName(): String - Returns driver class name (auto-detects 5.x vs 8.x)getUsername(): String - Returns username (default: "test")getPassword(): String - Returns password (default: "test")getDatabaseName(): String - Returns database name (default: "test")getTestQueryString(): String - Returns test query used for liveness checks ("SELECT 1")Connection Creation Methods:
createConnection(String queryString): Connection - Creates JDBC Connection (throws SQLException, NoDriverFoundException)getJdbcDriverInstance(): Driver - Returns Driver instance (throws NoDriverFoundException)Automatic JDBC URL Parameters:
useSSL=false - Added automatically if not presentallowPublicKeyRetrieval=true - Added automatically if not presentImportant Notes:
start() must be called first)Get the JDBC connection URL for the running MySQL container.
/**
* Returns the JDBC connection URL for this MySQL container.
* The URL includes the host, mapped port, database name, and automatic parameters
* for secure testing (useSSL=false, allowPublicKeyRetrieval=true).
*
* This method can only be called after the container has been started.
* Calling it before start() will return a URL with incorrect port information.
*
* Format: jdbc:mysql://host:port/database?useSSL=false&allowPublicKeyRetrieval=true[&urlParams]
*
* @return the JDBC URL string
* @throws IllegalStateException if called before container is started
*/
String getJdbcUrl();Usage Example:
MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))
.withDatabaseName("testdb");
mysql.start(); // Must start before calling getJdbcUrl()
String jdbcUrl = mysql.getJdbcUrl();
// Example: "jdbc:mysql://localhost:32768/testdb?useSSL=false&allowPublicKeyRetrieval=true"URL Details:
useSSL=false is added automatically if not specified (disables SSL for testing)allowPublicKeyRetrieval=true is added automatically if not specified (enables public key retrieval for testing)withUrlParam() are appendedURL Format:
jdbc:mysql://[host]:[mappedPort]/[database]?useSSL=false&allowPublicKeyRetrieval=true[&additionalParams]Common URL Examples:
jdbc:mysql://localhost:32768/test?useSSL=false&allowPublicKeyRetrieval=truejdbc:mysql://localhost:32768/testdb?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC&allowMultiQueries=trueGet the JDBC driver class name, with automatic detection of legacy vs. modern drivers.
/**
* Returns the JDBC driver class name for MySQL.
* Automatically detects whether the modern (8.x) or legacy (5.x) driver is available.
*
* The detection happens at runtime by attempting to load driver classes from the classpath.
* This method does not require the container to be started.
*
* Modern driver: com.mysql.cj.jdbc.Driver (MySQL Connector/J 8.x+)
* Legacy driver: com.mysql.jdbc.Driver (MySQL Connector/J 5.x)
*
* @return the driver class name
*/
String getDriverClassName();Usage Example:
MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"));
// Container does not need to be started for getDriverClassName()
String driverClass = mysql.getDriverClassName();
// Returns "com.mysql.cj.jdbc.Driver" if modern driver is on classpath
// Returns "com.mysql.jdbc.Driver" if only legacy driver is on classpathDriver Detection:
com.mysql.cj.jdbc.Driver (modern driver)com.mysql.jdbc.Driver (legacy driver)Driver Compatibility:
com.mysql.cj.jdbc.Driver - Recommended for MySQL 8.0+com.mysql.jdbc.Driver - For older applicationsRetrieve the database connection credentials.
/**
* Returns the username for database connections.
* Returns the default value "test" if not explicitly configured.
*
* @return the username (default: "test")
*/
String getUsername();
/**
* Returns the password for database connections.
* Returns the default value "test" if not explicitly configured.
*
* @return the password (default: "test")
*/
String getPassword();
/**
* Returns the database name.
* Returns the default value "test" if not explicitly configured.
*
* @return the database name (default: "test")
*/
String getDatabaseName();Usage Example:
MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))
.withDatabaseName("mydb")
.withUsername("myuser")
.withPassword("mypass");
mysql.start();
String username = mysql.getUsername(); // "myuser"
String password = mysql.getPassword(); // "mypass"
String database = mysql.getDatabaseName(); // "mydb"Credential Notes:
Create a JDBC connection to the containerized database.
/**
* Creates a new JDBC connection to the MySQL container.
* The connection is created using the container's JDBC URL, username, and password.
*
* This method requires the container to be started. It will throw SQLException if
* called before start() or if the container is not ready.
*
* The connection must be explicitly closed. Use try-with-resources for automatic cleanup.
* Multiple connections can be created from the same container instance.
*
* @param queryString optional query string parameters to append to the JDBC URL.
* Must include '?' if provided. Can be empty string.
* Example: "?allowMultiQueries=true" or ""
* @return a JDBC Connection object
* @throws SQLException if connection cannot be established (container not started,
* network issues, invalid credentials, timeout)
* @throws NoDriverFoundException if MySQL JDBC driver is not on classpath
* @throws IllegalStateException if called before container is started
*/
Connection createConnection(String queryString) throws SQLException;Usage Example:
import java.sql.Connection;
import java.sql.Statement;
import java.sql.ResultSet;
MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"));
mysql.start(); // Must start before creating connection
// Create connection without additional parameters
try (Connection conn = mysql.createConnection("")) {
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT VERSION()");
rs.next();
String version = rs.getString(1);
System.out.println("MySQL version: " + version);
}
// Create connection with additional parameters
try (Connection conn = mysql.createConnection("?allowMultiQueries=true")) {
Statement stmt = conn.createStatement();
stmt.execute("CREATE TABLE test (id INT); INSERT INTO test VALUES (1);");
}Connection Details:
Query String Parameter Format:
"?param=value": Single parameter (include '?' prefix)"?param1=value1¶m2=value2": Multiple parametersConnection Lifecycle:
MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"));
mysql.start();
// Create and use connection
try (Connection conn = mysql.createConnection("")) {
// Use connection
Statement stmt = conn.createStatement();
stmt.execute("SELECT 1");
} // Connection automatically closed here
// Container can still be used to create more connections
try (Connection conn2 = mysql.createConnection("")) {
// Another connection
}Obtain the JDBC driver instance for the MySQL connection.
/**
* Returns an instance of the MySQL JDBC driver.
* The driver is loaded and cached on first access.
*
* This method does not require the container to be started, but the driver
* must be on the classpath.
*
* @return a JDBC Driver instance
* @throws NoDriverFoundException if the MySQL JDBC driver is not on the classpath
*/
Driver getJdbcDriverInstance() throws NoDriverFoundException;Usage Example:
import java.sql.Driver;
import java.sql.Connection;
import java.util.Properties;
MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"));
// Container does not need to be started for getJdbcDriverInstance()
Driver driver = mysql.getJdbcDriverInstance();
Properties props = new Properties();
props.setProperty("user", mysql.getUsername());
props.setProperty("password", mysql.getPassword());
mysql.start(); // Must start before creating connection
Connection conn = driver.connect(mysql.getJdbcUrl(), props);
// Use connection...
conn.close();Driver Instance Notes:
NoDriverFoundException if driver not on classpathGet the SQL query used for container liveness checks.
/**
* Returns the SQL query used to test if the database is ready and accessible.
* This query is executed during container startup to verify the database is operational.
*
* This method does not require the container to be started.
*
* @return the test query string (always "SELECT 1" for MySQL)
*/
String getTestQueryString();Usage Example:
import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.utility.DockerImageName;
MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"));
// Container does not need to be started
String testQuery = mysql.getTestQueryString();
// testQuery == "SELECT 1"Note: This method is primarily used internally by Testcontainers for liveness checks, but can be useful if you need to know what query is used to verify database readiness.
import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.utility.DockerImageName;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class MySQLIntegrationTest {
public void testDatabaseOperation() throws SQLException {
try (MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))
.withDatabaseName("testdb")
.withUsername("testuser")
.withPassword("testpass")) {
mysql.start();
// Get connection details
String jdbcUrl = mysql.getJdbcUrl();
String username = mysql.getUsername();
String password = mysql.getPassword();
// Create connection and execute queries
try (Connection conn = mysql.createConnection("")) {
// Create table
Statement stmt = conn.createStatement();
stmt.execute("CREATE TABLE users (id INT PRIMARY KEY, name VARCHAR(100))");
// Insert data
stmt.execute("INSERT INTO users VALUES (1, 'Alice'), (2, 'Bob')");
// Query data
ResultSet rs = stmt.executeQuery("SELECT * FROM users ORDER BY id");
while (rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
System.out.println("User: " + id + " - " + name);
}
}
}
}
}import java.sql.DriverManager;
import java.sql.Connection;
MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"));
mysql.start();
// Load driver class
Class.forName(mysql.getDriverClassName());
// Create connection using DriverManager
Connection conn = DriverManager.getConnection(
mysql.getJdbcUrl(),
mysql.getUsername(),
mysql.getPassword()
);
// Use connection...
conn.close();
mysql.stop();import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import java.sql.Connection;
MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"));
mysql.start();
HikariConfig config = new HikariConfig();
config.setJdbcUrl(mysql.getJdbcUrl());
config.setUsername(mysql.getUsername());
config.setPassword(mysql.getPassword());
config.setDriverClassName(mysql.getDriverClassName());
config.setMaximumPoolSize(10);
HikariDataSource dataSource = new HikariDataSource(config);
try (Connection conn = dataSource.getConnection()) {
// Use connection from pool
}
dataSource.close();The MySQL module automatically adds the following parameters to JDBC URLs to facilitate secure testing:
These parameters are necessary for testing scenarios where SSL certificates are not configured and are automatically appended to the JDBC URL returned by getJdbcUrl().
Override Automatic Parameters:
// Override automatic SSL parameter
MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))
.withUrlParam("useSSL", "true")
.withUrlParam("trustCertificateKeyStoreUrl", "file:/path/to/keystore")
.withUrlParam("trustCertificateKeyStorePassword", "password");NoDriverFoundException: Thrown by getJdbcDriverInstance() or createConnection() if the MySQL JDBC driver is not found on the classpath. Ensure you have added a MySQL JDBC driver dependency:
<!-- Maven -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.33</version>
<scope>test</scope>
</dependency>// Gradle
testImplementation 'com.mysql:mysql-connector-j:8.0.33'SQLException: Thrown by createConnection() if the connection cannot be established within the configured timeout period. Common causes:
Solution:
// Ensure container is started
mysql.start();
// Increase connection timeout
mysql.withConnectTimeoutSeconds(180);
// Check container logs
mysql.withLogConsumer(new Slf4jLogConsumer(logger));IllegalStateException: Thrown by getJdbcUrl() or createConnection() if called before container is started.
Solution:
// Always start container before using connection methods
mysql.start();
String jdbcUrl = mysql.getJdbcUrl(); // Now safe to callgetJdbcUrl() after start() to get correct portSQLException and NoDriverFoundExceptionNoDriverFoundException early in testscreateConnection() over manual DriverManager usage