Search code examples
javamysqlhibernateenumshibernate-mapping

Read and Write generic Enum in hibernate


I have and object which contains a field

@Column(name = "section", nullable = false)
@Enumerated(EnumType.STRING)
private Enum section;

The reason for this is because the object is being used in three different projects and each one is going to provide its own Enum. It seems that writing the object is easy, but I can not read it and keep on getting

Caused by: java.lang.IllegalArgumentException: Unknown name value [BLAH] for enum class [java.lang.Enum]

Which of course makes perfect sense. So is there any way I can specify which Enum the value will be pointing to on per project basis?


Solution

  • You should define each enum property separately in each project.

    The best way is to remove the enum property from the current class, annotate that class with @Embeddable rather than @Entity, and in each project, create an entity class which embeds it and also declares its own project-specific enum property.

    You could also remove the enum from the current class, make the class abstract, replace @Entity with @MappedSuperclass, and have each project declare a subclass of it which declares a project-specific enum. However, it’s always best to prefer an aggregate design over an inheritance design.

    If you need polymorphism—that is, you need to be able to generically refer to each project’s entity from a single piece of code—you can have each project’s entity class implement an interface:

    public interface Sectionable<E extends Enum<E>> {
        E getSection();
        void setSection(E value);
    }
    
    @Entity
    public class Project1Entity
    implements Sectionable<Section1> {
        @Embedded
        private ProjectData data = new ProjectData();
    
        @Column(name = "section", nullable = false)
        @Enumerated(EnumType.STRING)
        private Section1 section;
    
        public ProjectData getData() {
            return data;
        }
    
        public void setData(ProjectData newData) {
            Objects.requireNonNull(newData, "Data cannot be null");
            this.data = newData;
        }
    
        @Override
        public Section1 getSection() {
            return section;
        }
    
        @Override
        public void setSection(Section1 section) {
            Objects.requireNonNull(section, "Section cannot be null");
            this.section = section;
        }
    }