Skip to main content

Notice: This Wiki is now read only and edits are no longer possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

EclipseLink/Examples/JPA/EnumListMapping


Example of a List<Enum> mapping

A common scenario to store a list of enumerations is a User 0..1 --> 0..* Role model. With the following requirements:

  • A User can have a number of Roles
  • The Roles have fixed values.
  • Role is not aware of any Users
  • Ability to query
  • Database integrity

Using a JPA vendor independent solution

You could use a User and Role Class to implement this model and map the association as a OneToMany. However this won't directly result in being able to use java Enum Types.

Using serialization

You could also serialize the collection to a binary field, but this would not allow for querying or automatic database integrity. See [1] and [2]

Using JPA 2.0 ElementCollection

As of JPA 2.0, this can also be mapped using an ElementCollection mapping.

Using EclipseLink @BasicCollection

This is an example solution of how to use a list of Enum Types directly in the Entity.

Note that in this example the database model constraints the Role values to values in a Role table. EclipseLink will never know there is Role table involved to validate the constraints. Whenever the Role Enum Type is changed the Role table must be updated accordingly (e.g. by adding a new row with the new string value of the new enum constant).

For information about the ObjectTypeConverter see: How to map an Enum type to coded values

Database model

create table USER1 (
   id serial not null,
   primary key (id)
);
 
create table USER_ROLE (
   userId serial not null,
   role varchar not null,
   primary key(userId, role)
);
 
create table ROLE (
   role varchar not null,
   primary key(role)
);
 
alter table USER_ROLE add foreign key (userId) references USER1 (id);
alter table USER_ROLE add foreign key (role) references ROLE (role);
 
insert into user1 values (1);
insert into role values ('admin');
insert into role values ('user');
insert into user_role (userId, role) values (1, 'admin');
insert into user_role (userId, role) values (1, 'user');

JPA code

The Role Enum Type:

public enum Role {
   admin,
   user
}

The User Entity:

@Entity
@Table(name="user1")
@ObjectTypeConverter (
    name = "roleEnumFromStringConversion",
    objectType = Role.class,
    dataType = String.class,
    conversionValues = {
        @ConversionValue(objectValue = "admin", dataValue = "admin"),
        @ConversionValue(objectValue = "user", dataValue = "user")
    }
)
public class User implements java.io.Serializable {
   ...
   private List<Role> roles;
   ...
 
   @BasicCollection (
       fetch=FetchType.EAGER,
       valueColumn=@Column(name="ROLE")
   )
   @CollectionTable (
       name="USER_ROLE",
       primaryKeyJoinColumns={
           @PrimaryKeyJoinColumn(name="USERID", referencedColumnName="ID")
       }
   )
   @Convert("roleEnumFromStringConversion")
   public List<Role> getRoles() {
       return roles;
   }
 
   public void setRoles(List<Role> roles) {
       this.roles = roles;
   }
}

EclipseLink specific ORM XML file

Instead of using annotations you could make the mapping in the EclipseLink specific orm.xml file as follows:

The User Entity:

public class User {
   ...
   private List<Role> roles;
   ...
 
   public List<Role> getRoles() {
       return roles;
   }
 
   public void setRoles(List<Role> value) {
       this.roles= value;
   }
}

The orm.xml file:

<?xml version="1.0" encoding="windows-1252" ?>
<entity-mappings
    xsi:schemaLocation="http://www.eclipse.org/eclipselink/xsds/persistence/orm xsd/eclipselink_orm_1_0.xsd"
    xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/orm"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0">
 
    <object-type-converter name="roleEnumFromStringConversion"
        object-type="enumlistmapping.Role" data-type="java.lang.String">
        <conversion-value object-value="admin" data-value="admin" />
        <conversion-value object-value="user" data-value="user" />
    </object-type-converter>
 
    <entity class="enumlistmapping.User" access="FIELD">
        <table name="USER1">
            <unique-constraint>
                <column-name>id</column-name>
            </unique-constraint>
        </table>
        <attributes>
            <id name="id">
                <column name="id" table="USER1" />
            </id>
            <basic-collection name="roles" fetch="EAGER">
                <value-column name="ROLE"/>
                <convert>roleEnumFromStringConversion</convert>
                <collection-table name="USER_ROLE">
                    <primary-key-join-column name="USERID" referenced-column-name="ID"/>
                </collection-table>
            </basic-collection>
        </attributes>
    </entity>
</entity-mappings>

Back to the top