# Org / Springframework / Samples / Petclinic / Model

## Overview

The `org.springframework.samples.petclinic.model` package contains the small set of reusable domain base classes that Petclinic uses to represent persisted model objects. Its primary job is to provide a consistent foundation for entity identifiers, simple named entities, and person-like records with validation annotations.

This package is intentionally lightweight: it does not implement business workflows itself, but it establishes the object shape and validation rules that other parts of the application can build on. The package-level documentation describes these classes as utilities used by the domain, which matches their role as shared model primitives rather than feature-specific entities.

## Key Classes and Interfaces

### [BaseEntity](src/main/java/org/springframework/samples/petclinic/model/BaseEntity.java:32)

`BaseEntity` is the shared superclass for model objects that need a database identifier. It is marked with `@MappedSuperclass`, which means JPA should treat its fields as part of the mapping for subclasses rather than as a standalone table.

The class provides three small but important behaviors:

- `getId()` returns the entity identifier.
- `setId(Integer id)` assigns the identifier.
- `isNew()` returns `true` when the identifier is still `null`, which is the package's simple signal that the object has not been persisted yet.

Key design points:

- The `id` field is annotated with `@Id` and `@GeneratedValue(strategy = GenerationType.IDENTITY)`, so persistence is responsible for generating the primary key.
- The class implements `Serializable`, which is a common requirement for JPA-backed domain objects.
- `isNew()` is useful for persistence logic elsewhere in the application because it gives callers a lightweight way to distinguish new objects from existing ones.

### [NamedEntity](src/main/java/org/springframework/samples/petclinic/model/NamedEntity.java:30)

`NamedEntity` extends `BaseEntity` and adds a required `name` property. It is also a `@MappedSuperclass`, so it exists to reduce duplication in subclasses that need both an identifier and a human-readable name.

Its methods are straightforward:

- `getName()` returns the current name.
- `setName(String name)` updates the name.
- `toString()` returns the name when present, otherwise it returns the literal string `"<null>"`.

Important details:

- The `name` field is annotated with both `@Column` and `@NotBlank`.
- `@NotBlank` means validation will reject empty or whitespace-only values.
- The custom `toString()` implementation makes logging and debugging more readable by preferring the domain name instead of the default object representation.

This class appears to be the shared base for simple lookup-style domain objects that are identified by a generated id and a single display name.

### [Person](src/main/java/org/springframework/samples/petclinic/model/Person.java:27)

`Person` is another `BaseEntity` subclass that models a person-like record with first and last name fields. Like `NamedEntity`, it is a `@MappedSuperclass`, so its columns are intended to be inherited by concrete JPA entities.

The class exposes four accessors:

- `getFirstName()` and `setFirstName(String firstName)` manage the first name.
- `getLastName()` and `setLastName(String lastName)` manage the last name.

Important details:

- Both fields are annotated with `@Column` and `@NotBlank`.
- Validation requires both names to be present and non-empty.
- The class itself is very small because it is designed as a shared building block for more specific domain types elsewhere in the system.

### [ValidatorTests](src/test/java/org/springframework/samples/petclinic/model/ValidatorTests.java:35)

`ValidatorTests` is a focused JUnit test that verifies Bean Validation works as expected for the model package. It is not part of the production model itself, but it documents and protects the validation contract on `Person`.

The class contains two methods:

- `createValidator()` constructs a `LocalValidatorFactoryBean`, calls `afterPropertiesSet()`, and returns it as a `Validator`.
- `shouldNotValidateWhenFirstNameEmpty()` creates a `Person`, sets `firstName` to an empty string, validates the object, and asserts that exactly one violation is produced for `firstName` with the message `"must not be blank"`.

This test is valuable because it verifies that the JSR-380 / Bean Validation integration is actually active, not just that annotations are present.

## How It Works

The package follows a simple inheritance pattern:

1. `BaseEntity` defines the shared persisted identity behavior.
2. `NamedEntity` and `Person` extend that base class when they need a generated identifier.
3. Validation annotations on the fields declare the expected invariants directly on the model.
4. `ValidatorTests` confirms that those annotations are enforced by the validation infrastructure.

A typical flow looks like this:

1. A concrete domain object inherits from one of these base classes.
2. JPA maps the inherited `id`, `name`, `firstName`, and `lastName` fields into the entity mapping.
3. Bean Validation runs before persistence or when a validator is invoked manually.
4. If a required string field is blank, validation produces a constraint violation using the default `must not be blank` message.
5. `isNew()` can be used by application code to decide whether an object has been persisted yet.

### Relationship diagram

```mermaid
flowchart TD
    BaseEntity["BaseEntity"] --> NamedEntity["NamedEntity"]
    BaseEntity --> Person["Person"]
    NamedEntity --> ValidatorTests["ValidatorTests"]
    Person --> ValidatorTests
```

## Data Model

The package defines a small inheritance-based model structure rather than a large graph of related entities.

### Shared identifier model

- `BaseEntity`
  - `id: Integer`
  - Generated by the database using identity strategy
  - Serves as the common persistence identity for subclasses

### Named model

- `NamedEntity`
  - Inherits `id`
  - Adds `name: String`
  - Requires a non-blank name

### Person model

- `Person`
  - Inherits `id`
  - Adds `firstName: String`
  - Adds `lastName: String`
  - Requires both names to be non-blank

The data model is intentionally minimal. These classes exist to standardize common fields and validation across concrete domain entities defined elsewhere in the application.

## Dependencies and Integration

This module sits close to the persistence and validation layers and depends on a few Jakarta and Spring components:

- `jakarta.persistence` annotations such as `@Id`, `@GeneratedValue`, `@MappedSuperclass`, and `@Column`
- `jakarta.validation.constraints.NotBlank` for field-level validation rules
- Spring's validation support in the test `LocalValidatorFactoryBean`
- JUnit 5 and AssertJ for the validation test
- `LocaleContextHolder` in the test to set the locale before validating messages

There are no resolved package dependencies in the index, which suggests this package is mostly a foundational leaf package that other modules depend on, not the other way around.

## Notes for Developers

- `BaseEntity.isNew()` only checks whether `id` is `null`. If your persistence model changes, keep in mind that this method assumes `null` means unsaved.
- `NamedEntity.toString()` returns `"<null>"` for missing names. That is helpful for debugging, but it also means logs will not show the default class name / hash code representation.
- `@NotBlank` is doing real work here. If you add new fields to similar model classes, annotate them explicitly so validation remains consistent.
- These classes are `@MappedSuperclass`, not standalone entities. Subclasses inherit mapping metadata, but these classes themselves are not intended to be queried directly as tables.
- `ValidatorTests` acts as a regression test for the validation stack. If validation messages or locale behavior change, this test is likely to be one of the first indicators.

## Source Files

- [src/main/java/org/springframework/samples/petclinic/model/BaseEntity.java](src/main/java/org/springframework/samples/petclinic/model/BaseEntity.java)
- [src/main/java/org/springframework/samples/petclinic/model/NamedEntity.java](src/main/java/org/springframework/samples/petclinic/model/NamedEntity.java)
- [src/main/java/org/springframework/samples/petclinic/model/Person.java](src/main/java/org/springframework/samples/petclinic/model/Person.java)
- [src/main/java/org/springframework/samples/petclinic/model/package-info.java](src/main/java/org/springframework/samples/petclinic/model/package-info.java)
- [src/test/java/org/springframework/samples/petclinic/model/ValidatorTests.java](src/test/java/org/springframework/samples/petclinic/model/ValidatorTests.java)