A lightweight Java library for generating SQL scripts populated with realistic fake data.
Explore the docs »
View Demo
·
Report Bug
·
Request Feature
Table of Contents
Instead of writing dozens of INSERT statements by hand, SQLForge lets you define your database schema in Java using a clean, fluent API—complete with column types, primary keys, foreign keys, NOT NULL, and UNIQUE constraints. It then generates a ready-to-run SQL script with CREATE TABLE, INSERT, SELECT, UPDATE, and DELETE statements populated by Datafaker. Foreign keys automatically reference primary keys generated for parent tables, keeping relational data consistent out of the box.
SQLForge started in October 2024 during my university database coursework. Setting up practice schemas and coming up with believable test data by hand was easily the most tedious part of every assignment, so I built a tool to automate it. This was one of my first Java projects when I was learning the ropes as a programmer, and I'm currently refreshing and cleaning it up.
SQLForge is published on JitPack. Add the JitPack repository and the dependency to your build.gradle.kts:
repositories {
mavenCentral()
maven("https://jitpack.io")
}
dependencies {
implementation("com.github.MrArCode:SQLForge:v0.2.0")
}SQLForge needs Java 25 or newer. Snippets for Maven and other build tools are on the JitPack page.
To build SQLForge from source, follow the steps below. You need:
- Java 8 or newer to start the Gradle wrapper
Note
The project is compiled with Java 25. Gradle uses a JDK 25 that it finds on your machine or downloads one automatically, so you don't need to change JAVA_HOME.
- Clone the repository:
git clone https://github.com/MrArCode/SQLForge.git cd SQLForge - Build the project using the Gradle wrapper:
(On Windows, run
./gradlew build
gradlew.bat buildinstead.)
Define your tables, pick the SQL operations you need, and build the script:
import io.github.mrarcode.sqlforge.generators.FakerDataGenerator;
import io.github.mrarcode.sqlforge.generators.ScriptBuilder;
import io.github.mrarcode.sqlforge.models.Column;
import io.github.mrarcode.sqlforge.models.Table;
import io.github.mrarcode.sqlforge.models.Types;
import java.nio.file.Files;
import java.nio.file.Path;
Table users = new Table("Users");
users.addColumn(new Column("ID", Types.INTEGER).setPrimaryKey(true).setNotNull(true));
users.addColumn(new Column("FirstName", Types.FIRSTNAME).setNotNull(true));
users.addColumn(new Column("Email", Types.EMAIL).setUnique(true).setNotNull(true));
Table orders = new Table("Orders");
orders.addColumn(new Column("OrderID", Types.INTEGER).setPrimaryKey(true).setNotNull(true));
orders.addColumn(new Column("UserID", Types.INTEGER).setForeignKey("Users(ID)").setNotNull(true));
orders.addColumn(new Column("OrderDate", Types.DATE_TIME).setNotNull(true));
String script = ScriptBuilder.builder()
.addTable(users) // add parent tables before tables that reference them
.addTable(orders)
.includeCreate()
.includeInsert(3)
.includeRead()
.withDataGenerator(new FakerDataGenerator())
.buildScript();
Files.writeString(Path.of("script.sql"), script);This produces a script.sql file like the following (with fresh random data on every run):
CREATE TABLE Users (
ID INT NOT NULL,
FirstName VARCHAR(255) NOT NULL,
Email VARCHAR(255) NOT NULL UNIQUE,
PRIMARY KEY (ID)
);
CREATE TABLE Orders (
OrderID INT NOT NULL,
UserID INT NOT NULL,
OrderDate DATETIME NOT NULL,
PRIMARY KEY (OrderID),
FOREIGN KEY (UserID) REFERENCES Users(ID)
);
INSERT INTO Users (ID, FirstName, Email) VALUES (1, 'Leonora', 'taylor.pagac@yahoo.com');
INSERT INTO Users (ID, FirstName, Email) VALUES (2, 'Yolanda', 'roger.herzog@gmail.com');
INSERT INTO Users (ID, FirstName, Email) VALUES (3, 'Deadra', 'alfredia.towne@hotmail.com');
INSERT INTO Orders (OrderID, UserID, OrderDate) VALUES (1, 1, '2026-09-18 15:15:30');
INSERT INTO Orders (OrderID, UserID, OrderDate) VALUES (2, 2, '2024-06-10 14:35:46');
INSERT INTO Orders (OrderID, UserID, OrderDate) VALUES (3, 3, '2025-07-15 10:06:38');
SELECT * FROM Users;
SELECT * FROM Orders;Main.java has a complete example that generates all CRUD operations (CREATE, INSERT, SELECT, UPDATE, and DELETE), prints the result to the console, and writes it to output/script.sql.
Run it with Gradle:
./gradlew runYou can also start io.github.mrarcode.sqlforge.Main from your IDE. The output/ folder is created automatically if it doesn't exist.
The Types enum controls both the SQL column type used in CREATE TABLE and the kind of fake data generated for that column:
| SQL type | Types values |
|---|---|
INT |
INTEGER |
VARCHAR(255) |
STRING, VARCHAR, TEXT, NAME, FIRSTNAME, LASTNAME, EMAIL, PHONENUMBER, PASSWORD, USER_AGENT, HEX_COLOR, FILE_NAME, LOREM_SENTENCE, UUID, ADDRESS, CITY, COUNTRY, ZIPCODE, IP_ADDRESS, MAC_ADDRESS, COMPANY, JOBTITLE, URL, NATIONALITY, CREDIT_CARD, IBAN, ISBN |
TEXT |
LOREM_PARAGRAPH |
VARCHAR(3) |
CURRENCY_CODE |
CHAR(1) |
CHAR |
DECIMAL(8,6) |
LATITUDE |
DECIMAL(9,6) |
LONGITUDE |
FLOAT |
FLOAT |
DOUBLE |
DOUBLE |
BOOLEAN |
BOOLEAN |
DATE |
DATE |
DATETIME |
DATE_TIME |
TIMESTAMP |
TIMESTAMP |
TIME |
TIME |
BLOB |
BLOB (inserts NULL by default) |
| Method | Description |
|---|---|
ScriptBuilder.builder() |
Creates a new script builder instance. |
addTable(Table table) |
Registers a table in the script. Tables are processed in the order they are added, so add referenced tables first. |
includeCreate() |
Includes CREATE TABLE statements with column constraints and keys. |
includeInsert(int count) |
Generates count INSERT statements per table. |
includeRead() |
Includes a SELECT * FROM <table>; query for each table. |
includeUpdate(int count) |
Generates up to count UPDATE statements per table, one per inserted row (requires a primary key). |
includeDelete(int count) |
Generates up to count DELETE statements per table, skipping rows that other rows still reference (requires a primary key). |
withDataGenerator(DataGenerator generator) |
Sets the data provider used for INSERT and UPDATE statements. |
buildScript() |
Builds and returns the full SQL script as a String. |
The script lists all CREATE TABLE statements first, followed by every INSERT, SELECT, UPDATE, and DELETE. DELETE statements go through the tables in reverse order, so foreign keys stay valid.
| Method | Description |
|---|---|
new Table(String tableName) |
Creates a table definition with the given name. |
addColumn(Column column) |
Appends a column to the table. |
All configuration setters return the Column instance for method chaining.
| Method | Description |
|---|---|
new Column(String columnName, Types dataType) |
Defines a column with the given name and type. |
setPrimaryKey(boolean isPrimaryKey) |
Marks the column as a primary key (auto-generates sequential IDs starting at 1). |
setNotNull(boolean isNotNull) |
Adds a NOT NULL constraint. |
setUnique(boolean isUnique) |
Adds a UNIQUE constraint. |
setForeignKey(String reference) |
Links the column to another table's primary key (e.g., "Users(ID)") and picks from already generated IDs. |
Want to plug in your own data source instead of Datafaker? Implement the DataGenerator interface:
public interface DataGenerator {
String generateData(Column column);
}generateData is called for every column except primary and foreign keys, which SQLForge fills in itself, and should return a valid SQL literal (such as a single-quoted string 'Alice', a number, or NULL).
SQLForge is under active development: the code is being cleaned up and fixed step by step, so the API and the generated SQL may still change.
Found a bug or have an idea? Open an issue.
Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.
If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement".
- Fork the Project
- Create your Feature Branch (
git checkout -b feat/amazing-feature) - Commit your Changes following Conventional Commits (
git commit -m 'feat: add support for PostgreSQL types') - Push to the Branch (
git push origin feat/amazing-feature) - Open a Pull Request
Distributed under the MIT License. See LICENSE for more information.
MrArCode – @MrArCode
Project Link: https://github.com/MrArCode/SQLForge
- Datafaker for realistic test data generation
- Best-README-Template