Using Hibernate with a map for the attributes of a table

So I have some code that represents a songs metadata, instead of having getters and setters for each field I put the values in map, each field is a String, and I have a seperate enum for each field. This makes the the code alot simpler

Im now looking to hibernatise this code, am Im going to lose this simplicity and have to have getters and setters for each field

public class Song
{

    protected final EnumMap<SongFieldKey,SongField> fields = new EnumMap<SongFieldKey,SongField>(SongFieldKey.class);


    public Song()
    {

    }


    /**
     * Return table cell datatype
     */
    public final SongField getField(SongFieldKey field)
    {
        return fields.get(field);
    }


    ................
}

public enum SongFieldKey
{
    ALBUM,
    ALBUM_ARTIST,
    ALBUM_ARTIST_SORT,
    ALBUM_SORT,
    AMAZON_ID,
    ARRANGER,
    ARTIST,
    ....
}

Answers


First of all Hibernate allows you to map Maps, Entity Mapa and Collections of simple datatypes and classes.

You would do this like that (for a Map<String, String>):

<map name="songFields">
  <key column="id"/>
  <index column="name" type="string"/>
  <element column="songField" type="string"/>
</map>

With such a entry in your hbm.xml, all the values you would put in the map would be stored in the newly created table called songFields.

So, in the worst case your example could work if you replaced the enum with a set of static String fields (which I assume you don't want to do, do you? :-))

When you try to replace the string with an Enum type, the mapping wont work out of the box. What you need to do is to somehow map your Enum class to varchar field in the DB.

This is the way how you can do it.

First, in your *.hbm.xml file define a new type of org.hibernate.type.EnumType class with your SongFieldKey as a enumClass parameter and 12 as a type parameter. (The magic 12 is defined in java.sql.Type as VARCHAR.)

 <hibernate-mapping>
    <typedef name="songFieldKey" class="org.hibernate.type.EnumType">
        <param name="enumClass">org.nowaq.hql.enums.SongFieldKey</param>
        <param name="type">12</param>
    </typedef>

    ...
 </hibernate-mapping>

When you have this in place, you can go ahead an write your <map ... replacing the string with songFieldKey like this:

<map name="songFields">
  <key column="id"/>
  <index column="fieldId" type="songFieldKey"/>
  <element column="field" type="string"/>
</map>

This should solve your "no getters and setters" problem. (I assumed no usage of SongField type for simplicity in the <element> tag so my map looked like this in code: private EnumMap<SongFieldKey, String> fields;.)

Anyway, make sure to understand the efficiency of this solution and take a look at these:

Hope this helps. Worked with Hibernate 3.4 and MySQL5 db.


Need Your Help

UIActivityIndicatorView Misaligned

iphone cocoa-touch position xib uiactivityindicatorview

I have UIActivityIndicatorView centered horizontally in a XIB.

How does time slicing happen in javascript?

javascript ecma262

or ecmascript but i wonder if how it actually happens depends more on the exact implimentation.

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.