Data Seeding

Spring-Hex provides factories and seeders for populating your database with development and test data — similar to Laravel’s seeder/factory system.

Table of Contents

  1. Data Seeding
    1. Overview
    2. Factories
      1. Generating a Factory
      2. Factory API
      3. Nested Factories
      4. Datafaker Dependency
    3. Seeders
      1. Generating a Seeder
      2. Implementing a Seeder
    4. Execution Order
      1. Controlling the Order
    5. Running Seeders
      1. Run All Seeders
      2. Run a Single Seeder
      3. What Happens Under the Hood
    6. Typical Workflow

Overview

The data seeding system has three parts:

Component Purpose
Factory Creates and persists fake entity instances using Datafaker
Seeder Orchestrates factories to populate the database
SeedRunner Dispatches db:seed commands to the right seeders

Factories

Factories generate fake entity instances. Like Laravel, create() persists to the database and make() builds in memory only.

Generating a Factory

spring-hex make:factory UserEntity
spring-hex make:factory OrderItemEntity -a order

This creates a factory @Component with a repository injection. If the repository doesn’t exist yet, it’s auto-generated.

@Component
@RequiredArgsConstructor
public class UserEntityFactory implements Factory<UserEntity> {

    private final UserEntityRepository repository;
    private static final Faker faker = new Faker();

    @Override
    public UserEntityRepository repository() {
        return repository;
    }

    @Override
    public UserEntity make() {
        return UserEntity.builder()
                .name(faker.name().fullName())
                .email(faker.internet().emailAddress())
                .build();
    }
}

The create() and count() methods are inherited from the Factory<T> interface — no boilerplate needed.

Factory API

Expression Behavior Use Case
factory.create() Builds and saves one entity Seeders, integration tests
factory.count(n).create() Builds and saves n entities Bulk seeding
factory.make() Builds in memory only Unit tests, assertions
factory.count(n).make() Builds n entities in memory Batch unit tests

Nested Factories

For entities with relationships (e.g., BookEntity belongs to AuthorEntity), call the dependency factory’s create() to persist it first:

@Component
@RequiredArgsConstructor
public class BookEntityFactory implements Factory<BookEntity> {

    private final BookEntityRepository repository;
    private final AuthorEntityFactory authorEntityFactory;
    private static final Faker faker = new Faker();

    @Override
    public BookEntityRepository repository() {
        return repository;
    }

    @Override
    public BookEntity make() {
        return BookEntity.builder()
                .title(faker.book().title())
                .author(authorEntityFactory.create())  // persisted before Book
                .build();
    }
}

Because authorEntityFactory.create() saves the AuthorEntity first, Hibernate won’t throw a TransientPropertyValueException.

Datafaker Dependency

Add Datafaker to your project:

<dependency>
    <groupId>net.datafaker</groupId>
    <artifactId>datafaker</artifactId>
    <version>2.4.2</version>
</dependency>

Seeders

Seeders orchestrate factories to populate the database.

Generating a Seeder

spring-hex make:seeder UserSeeder --entity UserEntity
spring-hex make:seeder BookSeeder --entity BookEntity

The first make:seeder call also auto-generates:

  • Seeder interface
  • SeedRunner infrastructure component

Implementing a Seeder

Fill in the seed() method — the factory handles persistence:

@Component
@RequiredArgsConstructor
@Slf4j
public class UserSeeder implements Seeder {

    private final UserEntityFactory factory;

    @Override
    public void seed() {
        log.info("UserSeeder: seeding...");

        factory.count(50).create();  // creates and saves 50 users

        log.info("UserSeeder: done");
    }
}

Execution Order

The SeedRunner contains an ordered list of seeder classes. When running db:seed --all, seeders execute in the order they appear in the list.

Controlling the Order

Open your SeedRunner and add seeders to the SEEDERS list. Place independent entities first, then entities that depend on them:

private static final List<Class<? extends Seeder>> SEEDERS = List.of(
        AuthorSeeder.class,      // no dependencies — runs first
        PublisherSeeder.class,   // no dependencies — runs second
        BookSeeder.class         // depends on Author and Publisher — runs last
);

Running Seeders

Run All Seeders

spring-hex db:seed --all

Executes every seeder in the SEEDERS list, in order.

Run a Single Seeder

spring-hex db:seed UserSeeder

Runs only the specified seeder by bean name.

What Happens Under the Hood

db:seed detects your build tool (Maven or Gradle) and runs:

# Maven
mvn spring-boot:run -Dspring-boot.run.arguments=--seed=UserSeeder

# Gradle
./gradlew bootRun --args=--seed=UserSeeder

The SeedRunner (a CommandLineRunner) picks up the --seed= argument and invokes the matching seeder.


Typical Workflow

# 1. Generate factories (repos auto-created if missing)
spring-hex make:factory AuthorEntity
spring-hex make:factory BookEntity

# 2. Generate seeders
spring-hex make:seeder AuthorSeeder --entity AuthorEntity
spring-hex make:seeder BookSeeder --entity BookEntity

# 3. Implement factory make() methods with Datafaker
# 4. Implement seeder seed() methods (call factory.create())
# 5. Add seeders to SeedRunner.SEEDERS in dependency order

# 6. Run
spring-hex db:seed --all

Back to top

Spring Hex CLI — Hexagonal Architecture scaffolding for Spring Boot

This site uses Just the Docs, a documentation theme for Jekyll.