Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to persist an EnumSet (using two database tables)?

I want to represent a set of options as an EnumSet in my entity and as a one-to-many relation in my database. How is this done properly? I can only find old (pre-annotations) answers or answers not using two tables.

I defined the following tables:

CREATE TABLE Users (
    id                      SERIAL PRIMARY KEY,
    name                    VARCHAR(255) NOT NULL UNIQUE
);

CREATE TABLE User_Options (
    user_id                 INT,
    user_option             VARCHAR(255),
    PRIMARY KEY (user_id, user_option),
    FOREIGN KEY (user_id) REFERENCES Users(id)
                ON DELETE CASCADE
                ON UPDATE CASCADE
);

this entity class:

@Entity(name = "Users")
public final class User {

    @Id
    @GeneratedValue
    private int id;

    @Column(nullable = false, unique = true)
    private String name;

    private final Set<UserOption> options;

    {
        this.options = EnumSet.noneOf(UserOption.class);
    }

    /* plain getter for id included */

    /* plain getter and setter for name included */

    @ElementCollection(fetch = FetchType.EAGER)
    @Enumerated(EnumType.STRING)
    @CollectionTable(name = "User_Options"
            , joinColumns = @JoinColumn(name = "user_id"))
    @Column(name = "user_option", nullable = false)
    public Set<UserOption> getOptions() {
        return this.options;
    }

}

and of course an enum:

public enum UserOption {

    OPTION_A,
    OPTION_B,
    OPTION_C;

}

When I start Tomcat I get the following exception:

org.hibernate.MappingException: Could not determine type for: java.util.Set, at table: Users, for columns: [org.hibernate.mapping.Column(options)]

This exception is the root of a bunch of exceptions causing each other. It causes a javax.persistence.PersistenceException (Unable to build EntityManagerFactory), which in turn causes some dependency injection exceptions.

I admit I'm not versed well enough in JPA/Hibernate to understand what I'm doing wrong. Can anybody help me out?

like image 265
Rinke Avatar asked Feb 11 '13 22:02

Rinke


People also ask

What is an EnumSet?

An EnumSet is a specialized Set collection to work with enum classes. It implements the Set interface and extends from AbstractSet: Even though AbstractSet and AbstractCollection provide implementations for almost all the methods of the Set and Collection interfaces, EnumSet overrides most of them.

What is EnumSet noneOf?

EnumSet. noneOf(Class elementType ) method in Java is used to create a null set of the type elementType. Syntax: public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType)

What is the use of EnumSet in Java?

The EnumSet is one of the specialized implementations of the Set interface for use with the enumeration type. A few important features of EnumSet are as follows: It extends AbstractSet class and implements Set Interface in Java. EnumSet class is a member of the Java Collections Framework & is not synchronized.

How do I create an empty EnumSet?

Use EnumSet. noneOf(Class) to create an empty EnumSet.


1 Answers

It turns out the answer is more simple than I thought. You cannot mix JPA-annotation on instance variables and getters. The annotations themselves are fine. I changed my entity class as follows and everything works fine now.

@Entity(name = "Users")
public final class User {

    @Id
    @GeneratedValue
    private int id;

    @Column(nullable = false, unique = true)
    private String name;

    @ElementCollection(fetch = FetchType.EAGER)
    @Enumerated(EnumType.STRING)
    @CollectionTable(name = "User_Options"
            , joinColumns = @JoinColumn(name = "user_id"))
    @Column(name = "user_option", nullable = false)
    private final Set<UserOption> options;

    {
        this.options = EnumSet.noneOf(UserOption.class);
    }

    /* plain getter for id included */

    /* plain getter and setter for name included */

    public Set<UserOption> getOptions() {
        return this.options;
    }

}
like image 185
Rinke Avatar answered Nov 04 '22 10:11

Rinke