8

In hibernate, is it possible to define a mapping for a class to a set of enums?

I've been able to find examples of how to define mappings of Sets and I've been able to find separate examples for how to map Enums, but I cannot figure out how to define a of Enums for a class.

Could anyone please provide me with an example?

This is being built on top of an existing application, so I cannot alter the database schema.

This is the relation I wish to model. Wicket is a normal class and WicketType is a Java Enum.

+----------------+    +------------+    +------------+
| Wicket         |    | Ref Table  |    | WicketType |
+----------------+    +------------+    +------------+
| INT     | W_ID |    |            |    | W_TypeId   |
| ....    |      | FK | W_ID       | FK | WicketType |
| INT     | TYPE |----| W_TypeId   |----|            |
+----------------+    +------------+    +------------+

Thanks again

Cuga
  • 17,668
  • 31
  • 111
  • 166

3 Answers3

4

A simpler way is

<typedef name="WicketTypeType" class="org.hibernate.type.EnumType">
  <param name="enumClass">Wicket</param>
  <param name="type">12</param>
</typedef>

<class  name="Wicket"...

    <set name="WicketType" table="Ref Table">
        <key column="W_ID" />
        <element column="W_TypeID" type="WicketTypeType"/>
    </set>

...
</class>
Mike
  • 41
  • 1
3

The sample code below shows how what you want can be achieved with annotations.

@Entity
@Table (name = "wicket")
public class Wicket {

    ...
    ...

    private List<WicketType> wicketTypes = new ArrayList<WicketType>();

    @CollectionOfElements(fetch=FetchType.EAGER)
    @JoinTable(
            name="wicket_wicket_types", // ref table.
            joinColumns = {@JoinColumn(name="wicket_id")}
    )
    @Column(name="wicket_type_id")
    public List<WicketType> getWicketTypes() {
        return this.wicketTypes;
    }

    public void setWicketTypes(List<WicketType> wicketTypes) {
        this.wicketTypes = wicketTypes;
    }
    ...
    ...
}

WicketType is a standard Java 5 Enum whose order and ordinals of enum declarations match order and the column (wicket_type_id) values in the wicket_type table.

public enum WicketType {
   WICKET_TYPE1, WICKET_TYPE2 ...
}
Venkat
  • 31
  • 3
2

Does this not do what you need?

To elaborate on the flippant initial response, the reference provides a means to use the ordinal of the enum to map enumerations.

In this case it's actually simpler than it looks, because you are hosting the enums in a set, you need to provide an accessor for the WicketType to the sub-type of IntEnumUserType, the super-type will take care of mapping the ordinal to the instance.

package test;

public class WicketTypeState extends IntEnumUserType<WicketType> {
    private WicketType wicketType;

public WicketTypeState() {
    // we must give the values of the enum to the parent.
    super(WicketType.class, WicketType.values());
}

    public WicketType getWicketType() {
        return wicketType;
    }

    public void setWicketType(final WicketType wicketType) {
        this.wicketType = wicketType;
    }
}

Define the mappings for the enum table:

<hibernate-mapping package="test">  
  <class name="Wicket" table="Wicket">
    <id name="id" column="ID"/>
    <set name="wicketTypes" table="WicketType" inverse="true">
      <key column="ID"/>
      <one-to-many class="test.WicketTypeState"/>
    </set>
  </class>
</hibernate-mapping>

Then for the type with the set of enums, define a set mapping for that property:

<hibernate-mapping package="test">
  <class name="WicketTypeState" lazy="true" table="WicketType">
    <id name="WicketType" 
      type="test.WicketTypeState"/>
  </class>
</hibernate-mapping>

This worked on my box(tm), let me know if you need any more info.

tekumara
  • 8,357
  • 10
  • 57
  • 69
Rich Seller
  • 83,208
  • 23
  • 172
  • 177
  • No-- that has a way to map an Enum, but doesn't specify how to use that Enum in a mapped Set. – Cuga Jul 14 '09 at 15:17
  • Per my comment, can you provide an example? Once you have defined how to map an enum using the ordinal, don't you just need to add the IntEnumUserType as the class in the set mapping? – Rich Seller Jul 14 '09 at 15:20
  • Thanks for helping. I provided a clearer example of what I'm trying to do. I'll try specifying the EnumUserType as the class in the mapping. – Cuga Jul 14 '09 at 15:35
  • Where you specify the mappings for the enum table (second block of code above)-- where does the property named "state" link to? – Cuga Jul 14 '09 at 15:57
  • that's a copy-paste error, just put together a test type for this to check the mappings – Rich Seller Jul 14 '09 at 16:01
  • Does this know to refer to the middle many-to-many table in the more detailed example? I can't figure out how to make hibernate to look for the relationship there... – Cuga Jul 14 '09 at 21:26
  • Sorry I totally missed the many-many relationship. This implementation is one-many. To make it many-many the WicketTypeState mapping needs to define a set as well and the WicketType needs to specify the save should be cascaded . I'll update it when back at a proper computer. – Rich Seller Jul 14 '09 at 21:49
  • What does it mean to have a many-many relationship here, do you have a field in the WicketType instances for the related Wicket instances? – Rich Seller Jul 14 '09 at 22:07
  • No, sorry for that confusion. It really is a one-to-many relationship allowing Wicket to have many WicketTypes (like a normal Set allows), with that relationship recorded in the middle lookup table. I'll edit the question to more accurately describe this. – Cuga Jul 14 '09 at 22:14
  • 1
    If it is one-to-many but against the Ref table, just change the table declaration in WicketType.hbm.xml to point to the Ref table and add another, standard one-to-one relationship to the WicketType table. – Rich Seller Jul 15 '09 at 10:44
  • no problem. One more point that might help, the WicketType state could easily be made generic by passing the Enum as a constructor argument (though I'm not familiar enough with hibernate to know how to map the constructor) – Rich Seller Jul 15 '09 at 14:36
  • Just a heads up: the link to the hibernate docs is broken. I would have taken a look at what it pointed to if it worked... – Tomislav Nakic-Alfirevic Sep 29 '10 at 13:11