PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteIf an application saves Java enum ordinals, inserting a constant can make an unchanged database value mean something different. For example, an enum declared as Pending, Paid, Shipped, Cancelled assigns Paid the ordinal 1. Insert Refunded after Pending, and ordinal 1 now means Refunded. The risk exists only when the application persists and later interprets ordinals; not every Java persistence mapping does this.
What an enum ordinal represents
Java assigns each enum constant an ordinal based on its position in the declaration, beginning at zero. Oracle’s Java SE 8 API defines ordinal() as the constant’s position in its enum declaration, with the initial constant assigned zero: Oracle Java SE 8 Enum.ordinal().
As an Amazon Associate I earn from qualifying purchases.
That position is useful for specialized structures such as EnumSet and EnumMap. Oracle’s API guidance says most programmers will have no use for ordinal() otherwise. A declaration position is not inherently a durable business identifier.
How a declaration change can reinterpret stored data
Consider the initial declaration and ordinals:
| Constant | Ordinal before change | Ordinal after inserting Refunded |
|---|---|---|
| Pending | 0 | 0 |
| Paid | 1 | 2 |
| Shipped | 2 | 3 |
| Cancelled | 3 | 4 |
| Refunded | — | 1 |
The example, described by Serguey Asael Shinder, shows the compatibility hazard: a previously stored 1 can now be read as Refunded instead of Paid, and a stored 2 as Paid instead of Shipped. The integers in existing rows have not changed; their meaning has. Removing or reordering constants can create the same kind of mismatch.
#1 Best Overall
This is a data-compatibility problem, not necessarily a compilation problem. The modified code can compile, and tests that do not check the persisted mapping can pass, while live records are interpreted differently. Whether it happens depends on how the application maps enums to storage and reads them back.
What to persist instead
Use explicit, stable codes
Give each value an explicit code intended for storage, and keep that code unchanged if you rearrange the enum declaration. For example:
enum OrderStatus {
PENDING(10),
PAID(20),
SHIPPED(30),
CANCELLED(40);
private final int code;
OrderStatus(int code) {
this.code = code;
}
int code() {
return code;
}
}
The persistence layer must store and resolve code(), not call ordinal(). The specific numbers above are illustrative; choose codes that fit the application’s storage and compatibility requirements.
Pin the mapping with a test
Test each constant-to-code association so an accidental code change is visible during development and review. A test can also check that codes are unique and that stored codes resolve to the intended constants. The important invariant is the mapping, not the declaration order.
Rank #3
Consider names only with a compatibility plan
Persisting enum names can make records easier to read than integers, but renaming a constant can break readers that expect the old name. If names are stored, treat them as external data identifiers: preserve old names through explicit mapping or migrate stored values when renaming. Neither names nor explicit numeric codes remove the need to decide how older application versions handle values they do not recognize.
How to handle a column that already stores ordinals
Changing the source declaration alone does not repair existing values. Before changing the mapping, identify the enum declaration that produced the stored integers and define an explicit conversion from each old ordinal to its intended meaning. Review the mapping against real data and the application’s history; if the old order or meaning cannot be established confidently, do not guess.
- Inventory the data. Find every column or payload that stores the enum and determine which application versions wrote it.
- Write the conversion map. Document the old integer-to-meaning mapping and the stable code or representation that will replace it.
- Validate before updating. Count values by old ordinal, check for unexpected or out-of-range values, and confirm the proposed conversion with the owners of the data.
- Migrate deliberately. Use a reviewed migration to translate stored values. For systems with rolling deployments, plan how old and new application versions will read and write during the transition; incompatible versions may otherwise disagree about a value’s meaning.
- Verify the result. Check that each migrated value resolves to the intended status and that the new mapping tests cover every supported value.
The migration’s exact rollout depends on the application and storage system. The essential point is that the data transformation must preserve meaning; a refactor that only changes enum source code cannot do that.
Why compatibility rules differ across systems
There is no universal rule that applies to every enum in every database or protocol. As one protocol-specific example, RFC 8881 allows minor versions to extend enumerated types with new values and prohibits deleting enum values. That is a rule for that protocol’s compatibility model, not a blanket requirement for Java applications or database schemas.
Likewise, a framework showing Java’s ordinal() method does not establish that a particular persistence framework stores ordinals. Drools 7.26.0.Final documents enum declarations that generate methods including ordinal(), compareTo(), and name(); the example demonstrates enum behavior, not a general ORM storage default: Drools 7.26.0.Final documentation.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




