# MariaDB4j: a MariaDB server that starts inside a Java test

> MariaDB4j is a Java launcher that extracts native MariaDB binaries from the classpath, starts them, and hands you a normal JDBC connection, so an integration test can have a real database without anything installed on the machine. The trade is a real server process per test, with a version of MariaDB chosen by you and a data directory that is discarded on restart unless you point it elsewhere.

**MariaDB4j/MariaDB4j** — MariaDB Embedded in Java JAR

- Repository: https://github.com/MariaDB4j/MariaDB4j
- Stars: 901 · Forks: 183
- Language: Java
- License: Apache-2.0
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/mariadb4j-mariadb4j

## A launcher, not an in-process database

MariaDB4j is described as MariaDB Embedded in Java JAR, and the readme is emphatic about what that means. It is a Java launcher for MariaDB, allowing you to use MariaDB from Java without any installation or external dependencies, with the line You do NOT have to have MariaDB binaries installed on your system to use MariaDB4j repeated in capitals.

It is worth being precise about the mechanism, because the word embedded is misleading. MariaDB4j does not implement a SQL engine inside the JVM. It starts the real MariaDB server as a separate native process, exactly the server you would install, and then gives you a JDBC connection to it.

The native binaries live in platform specific JARs named MariaDB4j-DB-win, linux and mac variants. The main MariaDB4j JAR depends on them through Maven transitive dependencies, and by default they are extracted from the classpath to a temporary base directory on the fly and then started by Java.

So the practical difference from installing MariaDB yourself is where the binary comes from and who starts it. There is no system install, no service to manage, no port conflict with a developer database, and no platform mismatch, because the correct binary for the platform comes in the dependency tree. What you get is a genuine MariaDB instance with genuine MariaDB semantics, which is the entire point, since the alternative would be an in-memory database that accepts the queries you wrote and rejects the ones you did not think about.

The project has been around since 2011, and the readme asks for sponsorship through OpenCollective, GitHub Sponsoring or Tidelift to ensure active maintenance.

## The DB API: install, configure, start, connect

The usage sequence is short, and the readme walks through it step by step with a worked example in the source tree, in MariaDB4jSampleTutorialTest.java.

The first step installs the database with a particular configuration using a shortcut.

```java
DB db = DB.newEmbeddedDB(3306);
```

The second step is where the interesting option lives. The data directory will by default be in a temporary directory too, and will automatically get scratched at every restart, which the readme says is suitable for integration tests. If you want something more permanent, perhaps an all-in-one application package, you specify a more durable location in the DBConfiguration.

```java
DBConfigurationBuilder configBuilder = DBConfigurationBuilder.newBuilder();
configBuilder.setPort(3306); // OR, default: setPort(0); => autom. detect free port
configBuilder.setDataDir("/home/theapp/db"); // just an example
DB db = DB.newEmbeddedDB(configBuilder.build());
```

Note the port comment: setting the port to zero asks the library to detect a free port automatically. That default is what makes parallel test execution safe, and it is also the thing that will break a hard-coded JDBC URL, which is why the next step has two variants.

Third, you start the database with db.start(). Fourth, you use it as standard JDBC, acquiring a Connection from the DriverManager, and the readme notes you could easily configure this URL to be used in any JDBC connection pool. MySQL uses a test database by default, and a root user with no password is also a default.

```java
Connection conn = DriverManager.getConnection("jdbc:mariadb://localhost/test", "root", "");
```

When MariaDB4j picks the port itself, a hard-coded URL is problematic, and the fix is to take the URL from the API instead.

```java
Connection conn = DriverManager.getConnection(configBuilder.getURL(dbName), "root", "");
```

The fifth step loads data from a SQL resource on the classpath with db.source("path/to/resource.sql").

## Using your own MariaDB version instead of the packaged one

If you need to start a specific DB version you already have rather than the one packaged in the JAR, the readme gives two ways to do it.

The configuration route is to call DBConfigurationBuilder setUnpackingFromClasspath(false) and setBaseDir("/my/db/"), or to pass the equivalent system properties, -DmariaDB4j.unpack=false and -DmariaDB4j.baseDir pointing at your own installation.

The other route is to pack your own version into a JAR and put it on the classpath, then override getBinariesClassPathLocation() in DBConfigurationBuilder to return where to find it, with the readme pointing at the source of the default implementation.

There is also a way back into a database you created earlier. To reopen a previously created database, use DB.openEmbeddedDB with the same configuration.

```java
DB.openEmbeddedDB(configBuilder.build());
```

This matters for the version coupling problem in a way that is easy to miss. The MariaDB version packaged in the JAR is whatever the maintainer chose, and it will not always match the version your application was developed against. Being able to point at a local installation or at your own JAR removes the works on my machine failure where the test database is a different major version from production.

The trade is that the dependency graph no longer carries the binaries, so the version becomes something your build has to supply. For a CI pipeline that wants reproducibility, letting the JAR carry the binaries is simpler; for a team testing against a specific server version, the override is the point.

## Spring, JUnit, the Maven plugin and the CLI

The readme points out something worth clarifying early: MariaDB4j can be used in any Java application on its own, and it is not dependent on dependency injection or the Spring Framework, with the note that the spring-core jar dependency is for a utility and unrelated to DI.

For Spring Boot users there is a ready-made MariaDB4jSpringService to reduce the coding and configuration needed, with an example application in mariaDB4j-app showing how to wire it up, and an alternative approach via MariaDB4jSpringServiceTestSpringConfiguration in the mariaDB4j-springboot module.

The springboot module exists for a specific reason. The DataSource initialization has to wait until MariaDB is ready to receive connections, so the module implements that. It is pulled in as a test dependency.

```groovy
dependencies {
   testCompile("ch.vorburger.mariaDB4j:mariaDB4j-springboot:3.1.0")
}
```

In that module the bean name of MariaDB4jSpringService is mariaDB4j, and the dataSource depends on it by name, so if you customise your MariaDB4j you have to make sure the name is correct.

The repository layout shows the packaging: mariaDB4j-core, mariaDB4j-junit, mariaDB4j-maven-plugin, mariaDB4j-pom-lite, mariaDB4j-springboot, mariaDB4j-app and the DBs/ directory, plus the usual build files including a Maven wrapper, a .java-version file, a .pre-commit-config.yaml and a flake.nix.

There is also a CLI entry point, listed in the readme table of contents alongside the DB API, the Spring and JUnit integration and the Maven plugin, and a section on the Maven artifacts and on the binaries themselves. The separate mariaDB4j-junit module is the piece that ties the database lifecycle to a test lifecycle, so the server starts and stops around the test rather than being managed by hand.

## Where MariaDB4j is the wrong choice

The trade-off is real and it is worth stating plainly: you are starting a database server process for your test, not running an in-memory fake.

That means every test class that wants a database pays for a server start, or for sharing one across the suite. That cost is why MariaDB4j has a JUnit module and a Spring module at all, and why the data directory defaults to something temporary, but it is still a process with a startup time and a port.

If your tests only need to prove that a repository method persists a row, an in-memory database or a mock is faster and sufficient, and a real server is overkill. The reverse mistake is more common and more expensive: a team writes tests against H2 or a mock, ships the code to a MySQL dialect in production, and discovers the difference in a bug rather than in a test. MariaDB4j is the answer to that second problem specifically.

The second limitation is the binary distribution. The native MariaDB binaries ship inside the JARs, which means the artefact size of your test classpath grows to include a database server for each platform, and the download is not trivial. There is also a portability question: the JAR set covers Windows, Linux and macOS, and the binaries have to match the architecture and the C library expectations of the machine running the test. The project does offer a path around the binary entirely, using your own installation or your own JAR, but that trades convenience for control.

The third is that this is not a production deployment story. The readme suggests an all-in-one application package as a possible use of a durable data directory, but embedding a database server in a shipped product is a different proposition from running one in CI, and if that is the goal a managed instance or a separate container is the saner design.

The alternative approaches differ in kind. Testcontainers runs the database in a container, which gives you the real server and real configuration files but adds a Docker dependency to the test run. An embedded pure-Java database such as H2 or Derby runs in the JVM with no process, but you are testing against a different implementation. MariaDB4j sits in the middle: the real MariaDB, started as a process, with no container runtime required.

## Conclusion

MariaDB4j suits a Java project whose integration tests need MySQL dialect SQL and real server behaviour, and which would rather not require every developer and CI agent to install a database server. It does not suit a team that wants database-free unit tests, since a server process is started per test, and it does not suit a production deployment, where a managed instance is the right answer. Before adopting it, confirm the MariaDB version it packages matches what your application targets, and read the port handling carefully, because the automatic free port detection changes the JDBC URL and any hard-coded URL in your test will break.

## FAQ

### What does MariaDB4j do and how does it work?

It is a Java launcher for MariaDB. The native binaries are in platform specific JARs that the main JAR depends on transitively, and by default they are extracted from the classpath to a temporary base directory on the fly and then started by Java, so you need no local MariaDB installation.

### How do I start a MariaDB4j database and connect to it?

Create one with DB.newEmbeddedDB for a shortcut or with a DBConfigurationBuilder for control over port and data directory, call db.start(), then connect over JDBC. The default MySQL setup is a test database with a root user and no password, and configBuilder.getURL(dbName) gives you the URL when the port is auto-detected.

### Can MariaDB4j use my own MariaDB version instead of the packaged one?

Yes. Call DBConfigurationBuilder setUnpackingFromClasspath(false) with setBaseDir pointing at your installation, or pass -DmariaDB4j.unpack=false and -DmariaDB4j.baseDir, or pack your own version into a JAR on the classpath and override getBinariesClassPathLocation(). You can also reopen an existing database with DB.openEmbeddedDB.

### Does MariaDB4j require Spring?

No. The readme states that MariaDB4j can be used in any Java application on its own and is not dependent on dependency injection or the Spring Framework. The spring-core dependency is for a utility and unrelated to DI, and the separate mariaDB4j-springboot module exists so the DataSource can wait until MariaDB is ready to accept connections.

### What licence does MariaDB4j use?

Apache-2.0, with LICENSE.txt and LEGAL.txt in the repository root. The repository also carries USERS.md and CONTRIBUTORS.md, and the latest listed release is mariaDB4j-3.3.1 from 2026-01-02 with the last push on 2026-10-18.

## Sources

- [Issues](https://github.com/MariaDB4j/MariaDB4j/issues)
- [License: Apache-2.0](https://github.com/MariaDB4j/MariaDB4j/blob/main/LICENSE)
- [MariaDB4j/MariaDB4j on GitHub](https://github.com/MariaDB4j/MariaDB4j)
- [README](https://github.com/MariaDB4j/MariaDB4j/blob/main/README.md)
- [Releases](https://github.com/MariaDB4j/MariaDB4j/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/mariadb4j-mariadb4j
