Master data management Β· features 286-305
πŸ›’οΈ SQL Server Β· MasterDataLabDB
πŸŽ“

How it works

One generic design serves all 25 master tables. Read this page once, then open any feature and expand Learn at the bottom of its page.

1. A request, step by step (saving a currency)

  1. The browser posts the form to POST /m/currencies/save.
  2. MasterController.save() asks MasterRegistry for the definition "currencies".
  3. It loads the entity (or creates a new Currency) and binds the request with ServletRequestDataBinder - only the fields listed in the definition.
  4. Bean Validation runs the annotations on Currency.java (@NotBlank, @Pattern ...).
  5. The definition's validator runs the rules that need the database (CurrencyService.validateCurrency: only one base currency).
  6. MasterService.save() (@Transactional) calls the hooks, then repository.saveAndFlush() β†’ Hibernate sends INSERT / UPDATE ... WHERE row_version = ?.
  7. It publishes MasterChangedEvent; MasterListeners writes the audit log and clears caches - in the same transaction.
  8. A SQL Server constraint error (uq_currency_code) is turned into a friendly message by DbErrors.
  9. Success β†’ redirect to the list with a flash message (Post/Redirect/Get).

2. Project layout

src/main/java/com/study/masterdata
β”œβ”€ domain/     JPA entities (BaseEntity + 30 tables)
β”œβ”€ repo/       Spring Data repositories
β”œβ”€ master/     the generic part
β”‚   β”œβ”€ FieldSpec, MasterDefinition   describe a master
β”‚   β”œβ”€ MasterRegistry                all 25 definitions
β”‚   β”œβ”€ MasterService                 CRUD + search (Specification)
β”‚   └─ MasterListeners               audit, caches, config history
β”œβ”€ feature/    business logic per feature (UnitService ...)
β”œβ”€ tool/       "Try it" panels (strategy pattern)
└─ web/        MVC controllers, REST API, view helpers
src/main/resources
β”œβ”€ db/migration/V1__schema.sql      tables (Flyway)
β”œβ”€ db/migration/V2__seed_data.sql   starter data
└─ templates/  Thymeleaf pages + tools/*.html

3. Ideas worth noticing

  • Soft delete vs hard delete - ⏸ sets active = 0; πŸ—‘ really deletes and fails while a foreign key still points at the row.
  • Optimistic locking - open the same record in two tabs, save both: the second one is refused (@Version row_version).
  • Pessimistic locking - running numbers lock the counter row (UPDLOCK) so 20 parallel requests get 20 numbers.
  • Effective dating - tax rates and exchange rates are looked up "as of" a date.
  • Caching - @Cacheable on lookups, parameters and config, cleared by an event listener.
  • Self-reference & cascade - categories (tree) and province β†’ district β†’ subdistrict.
  • Flyway - the schema is versioned SQL; Hibernate only validates it (ddl-auto=validate).

4. Add your own master (exercise)

  1. Create V3__department.sql with a table that has the 4 audit columns (copy one from V1).
  2. Create Department extends BaseEntity with Bean Validation annotations and label().
  3. Create DepartmentRepository extends MasterRepository<Department>.
  4. Add one MasterDefinition.of("departments", ...) in MasterRegistry.
  5. Restart: list, form, search, CSV, audit log and /api/masters/departments all work.

All masters

key β†’ table β†’ entity
FeatureMasterTableEntityTry-it panelAPI
286 πŸ—‚οΈ Categories category Category category-tree /api/masters/categories
287 🏷️ Tags tag Tag tag-cloud /api/masters/tags
288 πŸ“ Units of Measure unit Unit unit-converter /api/masters/units
289 🚦 Statuses status_def StatusDef workflow /api/masters/statuses
289 πŸ”€ Transitions status_transition StatusTransition workflow /api/masters/status-transitions
302 πŸ“š Lookup Types lookup_type LookupType lookup-overview /api/masters/lookup-types
302 πŸ“„ Lookup Values lookup_value LookupValue lookup-overview /api/masters/lookup-values
290 πŸ—ΊοΈ Provinces province Province address-cascade /api/masters/provinces
290 πŸ™οΈ Districts district District address-cascade /api/masters/districts
290 🏘️ Subdistricts subdistrict Subdistrict address-cascade /api/masters/subdistricts
305 🌍 Countries country Country country-summary /api/masters/countries
291 🏦 Banks bank Bank bank-check /api/masters/banks
292 πŸ’± Currencies currency Currency currency-format /api/masters/currencies
301 πŸ“ˆ Exchange Rates exchange_rate ExchangeRate fx-convert /api/masters/exchange-rates
300 🧾 Tax Rates tax_rate TaxRate tax-calc /api/masters/tax-rates
304 🀝 Payment Terms payment_term PaymentTerm due-date /api/masters/payment-terms
293 🎌 Holidays holiday Holiday holiday-calendar /api/masters/holidays
294 πŸ“… Fiscal Years fiscal_year FiscalYear fiscal-periods /api/masters/fiscal-years
295 πŸ”’ Running Numbers running_number RunningNumber running-number /api/masters/running-numbers
303 πŸ”€ Document Prefix / Suffix doc_prefix DocPrefix prefix-preview /api/masters/doc-prefixes
296 πŸ“ Document Templates doc_template DocTemplate template-preview /api/masters/templates
297 πŸŽ›οΈ System Parameters system_parameter SystemParameter parameter-read /api/masters/parameters
298 βš™οΈ System Config system_config SystemConfig config-resolve /api/masters/config
299 πŸ—£οΈ Languages app_language AppLanguage i18n-matrix /api/masters/languages
299 πŸ”€ Translations translation Translation i18n-matrix /api/masters/translations