Matchers
Matchers control which database objects are included in code generation and which features are enabled for each object.
Overviewβ
Matchers use pattern matching to include or exclude:
- Database schemas
- Tables and views
- Features per table (mock repos, test inserts, etc.)
Pattern Syntaxβ
Patterns support glob-style matching with negation:
| Pattern | Matches |
|---|---|
users | Exactly "users" |
user* | "users", "user_profiles", "user_sessions" |
*_backup | "orders_backup", "users_backup" |
*order* | "orders", "order_items", "customer_orders" |
public.* | All tables in "public" schema |
!*_temp | Negation: excludes anything ending in "_temp" |
Negation with !β
Prefix any pattern with ! to exclude matches. This is powerful when combined with wildcards:
matchers:
tables:
# Include all email columns EXCEPT email_process
- "*email*"
- "!email_process"
- "!*_backup"
Negation patterns are evaluated after positive patterns. A match against a negation pattern removes items that would otherwise be included.
types:
Email:
db:
# Match all columns containing 'email', except internal ones
column: ["*email*", "!email_hash", "!email_verified_at"]
model:
name: ["*email*", "!emailInternal"]
Basic Syntaxβ
Include Allβ
matchers:
tables: all
Include Specific Itemsβ
matchers:
tables:
- public.users
- public.orders
- sales.customers
Exclude Patternsβ
matchers:
tables:
include: all
exclude:
- "*_backup"
- "*_temp"
- flyway_*
Schema Matchingβ
matchers:
schemas: [public, sales, inventory]
# Or with exclude
schemas:
include: all
exclude: [pg_catalog, information_schema]
Feature Matchersβ
Each feature can be independently enabled per table.
Mock Repositoriesβ
Generate mock implementations for testing:
matchers:
mock_repos:
include: all
exclude:
- "*_audit"
- "*_log"
Generated code:
// Real repository (uses database)
public class UserRepoImpl implements UserRepo { ... }
// Mock repository (in-memory, for tests)
public class UserRepoMock implements UserRepo { ... }
Primary Key Typesβ
Generate type-safe ID wrappers:
matchers:
primary_key_types:
include: all
exclude:
- migrations
- schema_versions
Generated code:
// Instead of: Long id
public record UserId(Long value) {}
public record OrderId(Long value) {}
// Type-safe - can't mix IDs
userRepo.selectById(new UserId(1)); // OK
userRepo.selectById(new OrderId(1)); // Compile error!
Test Insertsβ
Generate test data factories:
matchers:
test_inserts:
include:
- public.users
- public.products
- public.orders
exclude: []
Generated code:
// Generate valid test data
UserRowUnsaved testUser = UserRowUnsaved.random();
// Or with specific overrides
UserRowUnsaved testUser = UserRowUnsaved.random()
.withEmail(new Email("test@example.com"))
.withIsActive(new IsActive(true));
Read-Only Repositoriesβ
Generate repositories without mutation methods:
matchers:
readonly:
include:
- "*_view"
- "audit_*"
- public.reports
Generated code:
// Only has select methods, no insert/update/delete
public interface AuditLogRepo {
List<AuditLogRow> selectAll();
Optional<AuditLogRow> selectById(AuditLogId id);
// No insert, update, or delete methods
}
Precise Typesβ
Generate length-constrained string types:
matchers:
precise_types:
include: all
Generated code:
// For VARCHAR(50) columns
public record VarcharMax50(String value) {
public VarcharMax50 {
if (value != null && value.length() > 50) {
throw new IllegalArgumentException("Value exceeds max length 50");
}
}
}
// For CHAR(10) columns (padded)
public record PaddedString10(String value) { ... }
Field Valuesβ
Generate field-level update types:
matchers:
field_values:
include:
- public.users
- public.products
Generated code:
// Update specific fields only
userRepo.update(userId, List.of(
UserFields.email(new Email("new@example.com")),
UserFields.isActive(new IsActive(false))
));