views:

2608

answers:

2

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

+1  A: 

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.

Rich Seller
No-- that has a way to map an Enum, but doesn't specify how to use that Enum in a mapped Set.
Cuga
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
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 <set> mapping.
Cuga
Where you specify the mappings for the enum table (second block of code above)-- where does the property named "state" link to?
Cuga
that's a copy-paste error, just put together a test type for this to check the mappings
Rich Seller
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
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
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
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
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
Thanks for all your help!
Cuga
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
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
A: 

Hi,

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