Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Storing EnumSet in a database?

Tags:

java

flags

So in C++/C# you can create flags enums to hold multiple values, and storing a single meaningful integer in the database is, of course, trivial.

In Java you have EnumSets, which appear to be quite a nice way to pass enums around in memory, but how do you output the combined EnumSet to an integer for storage? Is there another way to approach this?

like image 889
MalcomTucker Avatar asked Feb 04 '10 11:02

MalcomTucker


People also ask

Can we store enum in database?

First of all, in order to save enum values in a relational database using JPA, you don't have to do anything. By default, when an enum is a part of an entity, JPA maps its values into numbers using the ordinal() method. What it means is that without customizations JPA stores enum value as numbers.

How do you create an enum in a database?

In MySQL one can create an enum as such: USE WorldofWarcraft; CREATE TABLE [users] ( ID INT NOT NULL IDENTITY(1,1) PRIMARY KEY, username varchar(255), password varchar(255), mail varchar (255), rank ENUM ('Fresh meat', 'Intern','Janitor','Lieutenant','Supreme being')DEFAULT 'Fresh meat', );

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 the use of EnumSet in Java?

An enumSet is a Java Collections member, it is not synchronized. An enumSet is a high performing set implementation that works faster than the HashSet. All the elements in an enumSet must be of a single enumeration type that is specified when the set is created.


1 Answers

Storing the ordinal as a representation of the EnumSet is not a good idea. The ordinal numbers depend on the order of the definition in the Enum class (a related discussion is here). Your database may be easily broken by a refactoring that changes the order of Enum values or introduces new ones in the middle.

You have to introduce a stable representation of individual enum values. These can be int values again and represented in the proposed way for the EnumSet.

Your Enums can implement interfaces so the stable represenation can be directly in the enum value (adapted from Adamski):

interface Stable{
    int getStableId();
}
public enum X implements Stable {
    A(1), B(2);

    private int stableId;

    X(int id){
        this.stableId = id;
    }

    @Override public int getStableId() {
        return stableId;
    }
}

adapted from Adamski's code:

public <E extends Stable> int encode(EnumSet<E> set) {
  int ret = 0;

  for (E val : set) {
    ret |= (1 << val.getStableId());
  }

  return ret;
}
like image 69
Thomas Jung Avatar answered Oct 16 '22 12:10

Thomas Jung