# Org / Springframework / Samples / Petclinic / Model

## Overview

The `org.springframework.samples.petclinic.model` package contains the small set of shared domain model types used across Petclinic. It appears to provide the common JPA mapping and validation base classes that other domain objects can inherit from, keeping entity definitions consistent and reducing duplicated `id`, `name`, and person-name fields.

This package is intentionally small but foundational: it defines how model objects are persisted, how new entities are identified, and how Bean Validation is expected to behave for blank fields.

## Package Role

The package-level documentation in [`package-info.java`](src/main/java/org/springframework/samples/petclinic/model/package-info.java) describes these classes as utilities used by the domain. In practice, the package acts as a shared model layer for reusable persistence and validation conventions.

## Key Classes

### `BaseEntity`

[`BaseEntity`](src/main/java/org/springframework/samples/petclinic/model/BaseEntity.java) is the common superclass for persistent domain objects that need a generated identifier.

It is annotated with `@MappedSuperclass`, which means JPA will not map it as its own table, but subclasses inherit its `id` mapping. The class implements `Serializable`, which is a common requirement for persisted entities and session-friendly domain objects.

Key behavior:

- `getId()` returns the entity identifier.
- `setId(Integer id)` assigns the identifier.
- `isNew()` returns `true` when `id` is `null`, which is the package’s simple “unsaved entity” check.

Important details:

- The `id` field is annotated with `@Id` and `@GeneratedValue(strategy = GenerationType.IDENTITY)`, so persistence is expected to let the database assign the identifier.
- `isNew()` is a lightweight helper that downstream code can use to distinguish transient objects from persisted ones.

### `NamedEntity`

[`NamedEntity`](src/main/java/org/springframework/samples/petclinic/model/NamedEntity.java) extends `BaseEntity` and adds a required `name` property.

This class is also a `@MappedSuperclass`, so its mapping is inherited by concrete entities without creating a separate table. It exists for domain types that are primarily identified by an id and a human-readable name.

Key behavior:

- `getName()` and `setName(String name)` access the `name` field.
- `toString()` returns the current name when present, or `"<null>"` when the name has not been assigned yet.

Important details:

- `name` is annotated with `@Column` and `@NotBlank`, so blank values are invalid at validation time.
- The `toString()` implementation is intentionally defensive and avoids returning `null`.
- This class is the clearest sign that the package is designed around reusable model conventions rather than one-off entities.

### `Person`

[`Person`](src/main/java/org/springframework/samples/petclinic/model/Person.java) is another reusable mapped superclass, this time for people-related data.

It extends `BaseEntity` and stores the common name fields that other domain objects representing people can inherit.

Key behavior:

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

Important details:

- Both fields are annotated with `@Column` and `@NotBlank`.
- The class is not a concrete entity by itself; it is a base type for richer people-related domain objects elsewhere in the application.
- The validation annotations make the class enforce a non-empty first and last name before an object is considered valid.

### `ValidatorTests`

[`ValidatorTests`](src/test/java/org/springframework/samples/petclinic/model/ValidatorTests.java) is a small test class that confirms Bean Validation is wired correctly for the package’s model objects.

It does not test business logic so much as infrastructure behavior: that a blank `firstName` produces the expected validation failure.

Key behavior:

- `createValidator()` creates a `LocalValidatorFactoryBean`, initializes it, and returns it as a `Validator`.
- `shouldNotValidateWhenFirstNameEmpty()` creates a `Person`, leaves `firstName` blank, validates it, and asserts that exactly one violation is produced.

Important details:

- The test sets `LocaleContextHolder` to `Locale.ENGLISH` before validation so the assertion on the message text is stable.
- The expected error is attached to the `firstName` property path and uses the standard message `"must not be blank"`.
- This test acts as a guardrail for framework upgrades, especially around Hibernate Validator and Bean Validation message behavior.

## How It Works

A typical pattern in this package is inheritance plus annotation-based validation:

1. A concrete domain object elsewhere in the application extends `BaseEntity`, `NamedEntity`, or `Person`.
2. JPA inherits the mapped identifier or field mappings from the superclass.
3. Bean Validation checks the inherited fields because the constraints live directly on the superclass fields.
4. Application code can use `isNew()` to determine whether a record has been persisted yet.
5. For named entities, `toString()` gives a readable representation without forcing callers to check for `null`.

This keeps the domain layer simple: shared concerns are centralized once, and concrete models can focus on their own extra fields.

## Data Model

The package defines a small inheritance-based model structure:

```mermaid
classDiagram
class BaseEntity {
  +Integer id
  +Integer getId()
  +void setId(Integer id)
  +boolean isNew()
}
class NamedEntity {
  +String name
  +String getName()
  +void setName(String name)
  +String toString()
}
class Person {
  +String firstName
  +String lastName
  +String getFirstName()
  +void setFirstName(String firstName)
  +String getLastName()
  +void setLastName(String lastName)
}
NamedEntity --|> BaseEntity
Person --|> BaseEntity
```

Relationship summary:

- `BaseEntity` is the persistence foundation for all shared entities in this package.
- `NamedEntity` adds a required display name on top of `BaseEntity`.
- `Person` adds separate first and last name fields on top of `BaseEntity`.

## Dependencies and Integration

This package integrates with a small set of JPA and validation APIs:

- `jakarta.persistence` for entity mapping annotations such as `@MappedSuperclass`, `@Id`, `@GeneratedValue`, and `@Column`
- `jakarta.validation` for `@NotBlank`
- Spring’s validation support in the test class via `LocalValidatorFactoryBean`
- Spring’s locale context in tests via `LocaleContextHolder`

The package does not show any direct dependencies on application services or repositories in the indexed sources. Its role is deliberately low-level and reusable.

## Notes for Developers

- These classes are meant to be inherited, not usually instantiated directly in application code.
- Because the fields are annotated directly, validation should be performed against the actual object instance after binding or before persistence.
- `BaseEntity.isNew()` treats only `null` as new; any non-null id is considered persisted.
- `NamedEntity.toString()` returns `"<null>"` instead of `null`, which makes logging and UI rendering safer.
- The test in [`ValidatorTests`](src/test/java/org/springframework/samples/petclinic/model/ValidatorTests.java) is a useful reference for how validation is expected to behave for these model types.

## Related Sources

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