Difference between revisions of "EclipseLink/Examples/JPA/EnumListMapping"

From Eclipsepedia

Jump to: navigation, search
(EclipseLink specific ORM XML file)
(Using JPA 2.0 ElementCollection)
 
(4 intermediate revisions by 2 users not shown)
Line 1: Line 1:
 +
[[Category:EclipseLink/Example/JPA|EnumListMapping]]
 +
 
= Example of a List<Enum> mapping =
 
= Example of a List<Enum> mapping =
  
Line 17: Line 19:
 
You could also serialize the collection to a binary field, but this would not allow for querying or automatic database integrity.
 
You could also serialize the collection to a binary field, but this would not allow for querying or automatic database integrity.
 
See [http://dev.eclipse.org/mhonarc/lists/eclipselink-users/msg00915.html] and [http://dev.eclipse.org/mhonarc/lists/eclipselink-users/msg00918.html]
 
See [http://dev.eclipse.org/mhonarc/lists/eclipselink-users/msg00915.html] and [http://dev.eclipse.org/mhonarc/lists/eclipselink-users/msg00918.html]
 +
 +
== Using JPA 2.0 ElementCollection ==
 +
As of JPA 2.0, this can also be mapped using an [[EclipseLink/Examples/JPA/2.0/ElementCollections|ElementCollection]] mapping.
  
 
== Using EclipseLink @BasicCollection ==
 
== Using EclipseLink @BasicCollection ==
Line 113: Line 118:
 
<source lang=java>
 
<source lang=java>
 
public class User {
 
public class User {
 +
  ...
 
   private List<Role> roles;
 
   private List<Role> roles;
 +
  ...
  
 
   public List<Role> getRoles() {
 
   public List<Role> getRoles() {

Latest revision as of 10:54, 15 June 2010


Contents

[edit] 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

[edit] 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.

[edit] 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]

[edit] Using JPA 2.0 ElementCollection

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

[edit] 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

[edit] 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');

[edit] 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;
   }
}

[edit] 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>