Java Enum and How to Persist It
Should use Enums any time you need to represent a fixed set of constants
- A simple instruction to Java Enum
- How to use Enum
- Persist an Enum object
What is an Enum
An enum type (or enumerated type) is a type whose fields consist of a fixed set of constants. Eg: Seasons of a year. In plain English, “to enumerate” means to count off or name one by one from a list.
- We can add fields, constructors and methods to an enum.
- Enum can also implement interfaces.
- When anything else other than constants is there, comma-separated constants should be terminated with a semicolon. Otherwise, the semicolon is optional.
- We can use
==
to compare enum constants effectively because constants are final and we cannot call an enum’s constructors to create more constants. - Enums supports the
switch
statement.
public enum Season {
SPRING,
SUMMER,
AUTUMN,
WINTER;
}
Enum fields and methods
Enum constructor:
protected Enum(String name, int ordinal)
Parameters:
name
- The name of this enum constant, which is the identifier used to declare it.
- Should use toString to return a more user-friendly name.
ordinal
:- Its position in its enum declaration, starts from 0.
- Should avoid to use it.
- It is designed for use by sophisticated enum-based data structures, such as
EnumSet
andEnumMap
.
Overridden methods:
clone ()
– ThrowsCloneNotSupportedException
. This guarantees that enums are never cloned, which is necessary to preserve their “singleton” status.equals ()
– Returns true if the specified object is equal to this enum constant.finalize ()
– to ensure that constants cannot be finalized.hashCode ()
– because equals is overriddentoString ()
– to return constant’s name.compareTo()
– Enum implements Comparable.
Important methods
-
name()
– returns constant’s name. -
ordinal()
– position of the constant within enum type. compareTo () compares ordinals. -
The values()
static method of the enum returns an array of all constants that are declared in the enum. It’s not part of Enum’s java documentation. It’s added by the compiler.for (Planet p : Planet.values()) { System.out.printf("Your weight on %s is %f%n", p, p.surfaceWeight(mass)); }
-
getDeclaringClass()
- Returns the Class object corresponding to this enum constant’s enum type.- Two enum constants e1 and e2 are of the same enum type if and only if
e1.getDeclaringClass() == e2.getDeclaringClass()
- The value returned by this method may differ from the one returned by the Object.getClass() method for enum constants with constant-specific class bodies.
- Two enum constants e1 and e2 are of the same enum type if and only if
JSON Representation of Enum
Enums are POJOs. They can be represented as a JSON. //todo
Benefits of using Enum
- More readable code.
- Enum is type-safe. You cannot assign anything else other than predefined Enum constants to an Enum variable
- Set of Constant declaration.
- Can be usable in switch-case.
Persisting Enums in JPA
- persist the ordinal with
@Enumerated(EnumType.ORDINAL)
- persist the String with
@Enumerated(EnumType.STRING)
. - JPA 2.1
@Converter
Annotation - Database specification for Enum data type // todo
- Postgres
- MySQL
Ordinal
The Good
ORDINAL
can use a SMALLINT which is the most compact db option.- Rename filed without pressure.
The Bad
- New enum elements must be added to the end of the list. If we add a new value in the middle or rearrange the enum’s order, we’ll break the existing data model.
- Removing existing elements from ann Enum will require to shift all entries in case you are using
ORDINAL
.
The Others
@Enumerated
column does not need to take theORDINAL
EnumType value since that’s used by default.
String Value
- A string is bigger than, like, int. So will use more space and hence slower.
- Renaming an enum value will still break the database data.
Using @Converter
public enum Season {
SPRING("1"),
SUMMER("2"),
AUTUMN("3"),
WINTER("4");
private String code;
Season(String code) {
this.code = code;
}
}
@Entity @Data
public class Flower {
@Id private Long id;
private Season season;
}
@Converter(autoApply = true)
public class SeasonConverter implements AttributeConverter<Season, String> {
@Override
public String convertToDatabaseColumn(Season attribute) {
if (attribute == null) {
return null;
}
return attribute.getCode();
}
@Override
public Season convertToEntityAttribute(String dbData) {
if (dbData == null) {
return null;
}
return Stream.of(Season.values())
.filter(s -> s.getCode().equalsIgnoreCase(dbData))
.findFirst()
.orElseThrow(IllegalArgumentException::new);
}
}
@Test
public void canSave() {
Flower flower = new Flower();
flower.setId(1L);
flower.setSeason(Season.SPRING);
final Flower save = flowerRepository.save(flower);
Assert.assertTrue(save != null);
}