| name | database-table-creator |
| description | Creates database table with full Kotlin synchronization (SQL migration → Table → Entity → Repository → Tests). Use when adding new database tables or entities. |
| allowed_tools | ["Read","Write","Edit","Bash","Glob","Grep"] |
Database Table Creator Skill
Creates complete database table implementation with SQL migration, Kotlin code, and comprehensive tests.
What This Skill Does
Generates:
- SQL Migration - PostgreSQL table with soft deletes, indexes, triggers
- Kotlin Table Object - Exposed ORM table definition (extends UUIDTable)
- Entity Data Class - Kotlin entity implementing Entity
- Repository Interface + Implementation - CRUD operations with soft delete
- Repository Tests - Comprehensive test coverage (7+ tests)
- Factory Bean - Dependency injection registration
Critical Rules
Database Design (rules/database/SCHEMA.md)
SQL Requirements:
- ❌ NO foreign key constraints (NEVER use REFERENCES or FOREIGN KEY)
- ✅ Use TEXT for strings (NOT VARCHAR)
- ✅ Include: id (UUID), created_at, updated_at, deleted_at
- ✅ ALL indexes MUST have
WHERE deleted_at IS NULL
- ✅ Add soft delete index:
WHERE deleted_at IS NOT NULL
- ✅ Add update trigger for updated_at
Kotlin Requirements:
- ✅ Table MUST extend
UUIDTable (NOT Table)
- ✅ Entity MUST implement
Entity<Instant>
- ✅ ALL queries MUST filter
deletedAt.isNull()
- ❌ NO
!! operators (forbidden by pre-commit hooks)
- ✅ Soft delete only (set deletedAt, never hard delete)
Workflow
Step 1: Create SQL Migration
Location: database-migration/sql/{number}-{description}.sql
CREATE TABLE {table_name} (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL,
email TEXT,
status TEXT DEFAULT 'active',
user_id UUID,
count INTEGER DEFAULT 0,
is_active BOOLEAN DEFAULT true,
metadata JSONB,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP,
deleted_at TIMESTAMP
);
CREATE UNIQUE INDEX idx_{table_name}_email_unique
ON {table_name}(email) WHERE deleted_at IS NULL;
CREATE INDEX idx_{table_name}_user_id
ON {table_name}(user_id) WHERE deleted_at IS NULL;
CREATE INDEX idx_{table_name}_deleted_at
ON {table_name}(deleted_at) WHERE deleted_at IS NOT NULL;
CREATE TRIGGER update_{table_name}_updated_at
BEFORE UPDATE ON {table_name}
FOR EACH ROW
EXECUTE FUNCTION update_updated_at();
Critical:
- Use TEXT not VARCHAR
- NO REFERENCES or FOREIGN KEY
- ALL indexes have WHERE clause
- Soft delete index required
- Update trigger required
Step 2: Run Migration
./gradlew :app:module-repository:flywayMigrate
Verify success before proceeding.
Steps 3-10: Kotlin Implementation
See kotlin-templates.md for all Kotlin code templates (Table, Entity, Repository, Factory Bean, Tests).
Follow this order:
- Step 3 — Table object (extends
UUIDTable, use text() not varchar())
- Step 4 — Entity data class (implements
Entity<Instant>)
- Step 5 — Constants/Enums (if needed)
- Step 6 — Repository interface
- Step 7 — Repository implementation (
db.primary for writes, db.replica for reads, ALWAYS filter deletedAt.isNull())
- Step 8 — Factory bean registration
- Step 9 — Repository tests (minimum 7 tests, must include soft delete verification)
- Step 10 — Run tests:
./gradlew test
Common Mistakes to Avoid
See examples.md for common mistakes and anti-patterns.
Success Criteria
✅ SQL migration runs successfully
✅ Uses TEXT (not VARCHAR)
✅ NO foreign key constraints
✅ All indexes have WHERE clause
✅ Kotlin Table extends UUIDTable
✅ Entity implements Entity
✅ All queries filter deletedAt.isNull()
✅ No !! operators
✅ Soft delete only (no hard delete)
✅ Factory bean registered
✅ All 7+ tests pass