One key issue that is to my feeling is not addressed sufficiently is
how we map an Enum.
1./ An enum is not allowed to have a Persistent Counterpart
2./ An enum has the limited choice of
- @Enumerated(EnumType.STRING)
- @Enumerated(EnumType.ORDINAL)
Which is in real case scenario's too limiting.
The limitations seem to originate from the idea that "enums that have
state are not supported".
I explain both.
Consider the Following Table representing a Male/Female Choice in the
DB
Table: SEX
SEX_ID SEX_NAME
M Male
F Female
N/A Not Established
Two Issues come up, matching with the earlier listed limitations.
1./ Sex has also a Descriptive Field, the Name. It is common to have a
fixed set of Categories defined on the DB, and have additional
attributes associated with them. Although Constant, those attributes
can be specific to the environment. One might decide on the Database
end to just rename 'Not Established' to 'Unknown' without affecting the
integrity of the Database, because the PK is based on SEX_ID, not
SEX_NAME. It would be much more flexible to have an Enum, as a
READ-ONLY entity do a one-time SYNC/FETCH to sync up additional
Attributes once the ID is established (the Enum constants are defined).
2./ Even though on the Database the SEX_ID is keyed by M/F, Most
likely, one would like this to be defined as MALE / FEMALE Enum
Constants. In Addition, The Syntax of an Enum does not allow for
Special Characters (forward slashes, spaces, etc). So 'N/A' cannot be
represented by an Enum Constant with the same name. Also instead of
using a Alphabetic ID, one might decide on the Database end to key to
the Enum Constants based on a numeric Key. A numeric Key can also not
be represented as an Enum Constant, and the ORDINAL will rarely match
the database generated keys.
Or even a worse scenario for 2./ but typical: Everywhere the ENUM is
being keyed using a numeric value, but the value of the key is
different from Environment to Environment (Production versus QA). So
the Key associated with the ENUM Constants first need to be
fetched/synced from Database. Kind of a combination of 1./ and 2./
together.
These two issues makes it extremely difficult to use Enum's in a
pre-existing Database, with a schema that was not designed for use with
JPA specifically.
This is how the Enum could look like with such features enabled:
@Enumerated(EnumType.CUSTOM)
@OneTimeSync
enum Sex {
MALE,
FEMALE,
UNKNOWN;
@Id
@Column('sex_id')
@Map({
@MapEntity('M',Sex.MALE),
@MapEntity('F',Sex.FEMALE),
@MapEntity('N/A',Sex.UNKNOWN)
} )
public String id;
@ImmutableAttribute
@Column(sex_name)
public String description;
}
or for a Numerically Keyed value, but keys fetched from Database:
@Enumerated(EnumType.CUSTOM)
@OneTimeSync
enum Sex {
MALE,
FEMALE,
UNKNOWN;
@SyncId // Id/Key to be used for a one-time-sync.
@Column('sex_id')
@Map({
@MapEntity('M',Sex.MALE),
@MapEntity('F',Sex.FEMALE),
@MapEntity('N/A',Sex.UNKNOWN)
} )
public String id;
@Id
@ImmutableAttribute
@Column('sex_key')
public Long key;
@ImmutableAttribute
@Column(sex_name)
public String description;
}