-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 10 posts ] 
Author Message
 Post subject: How to map a Map<String,String> in EJB3?
PostPosted: Wed Feb 15, 2006 8:59 am 
Newbie

Joined: Mon Nov 08, 2004 6:03 pm
Posts: 8
I'm having trouble finding out how to annotate a persistent object that has a Map<String,String>. I have a table that contains 3 columns, a foreign key to the persistent object's table and 2 columns that are just plain old strings. I can't figure out how to annotate this. All the examples show a map of a string to another persistent object. Is there a way to do this?

Thanks for any help!
Mike


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 15, 2006 10:25 am 
Regular
Regular

Joined: Sun May 08, 2005 2:48 am
Posts: 118
Location: United Kingdom
I'm sorry I cant help with annotations, but a mapping for that sort of arrangement might look like this:

Code:
<hibernate-mapping>
   <class name="com.foobar.Head" table="object_head">
      <id name="objectHeadId" type="long" column="object_head_id">
         <generator class="native"/>
      </id>

      <property ... />

      <map name="attributes" table="object_head_attrs" cascade="all">
         <key column="object_head_id" not-null="true"/>
         <map-key column="name" type="string"/>
         <element not-null="true" type="string" column="value"/>
      </map>
   </class>
</hibernate-mapping>


I believe the anotations are a shortcut to generating the above file.

The <map table="object_head_attrs"> is the equavalent table you are referring to, with the object_head_id being a joinable foriegn key owned by the com.foobar.Head class.

Your POJO has the fields (with appropiate getters/setters not shown):
Code:
private long objectHeadId;
private Map attributes;


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 15, 2006 10:36 am 
Newbie

Joined: Mon Nov 08, 2004 6:03 pm
Posts: 8
Thanks for the reply. I'm trying to do something like this:

Code:
    @MapKey(name="name")
    @Column(name="value")
    @OneToMany(cascade={ CascadeType.ALL },
               fetch=FetchType.EAGER)
    @JoinTable(table=@Table(name="object_head_attrs"),
               joinColumns={@JoinColumn(name="object_head_id",
                                        referencedColumnName="object_head_id")})
    public Map<String,String> getAttrs() {
        return attrs;
    }

    public void setRoles(Map<String,String> attrs) {
        this.attrs= attrs;
    }


But I get the following exception:

Code:
org.hibernate.AnnotationException: Associated class not found: java.lang.String at
org.hibernate.cfg.annotations.MapBinder.bindKeyFromAssociationTable(MapBinder.java:58) at
org.hibernate.cfg.annotations.MapBinder.access$000(MapBinder.java:25) at
org.hibernate.cfg.annotations.MapBinder$1.secondPass(MapBinder.java:48) at
org.hibernate.cfg.CollectionSecondPass.doSecondPass(CollectionSecondPass.java:35) at
org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1023) at
org.hibernate.cfg.AnnotationConfiguration.secondPassCompile(AnnotationConfiguration.java:218) at
org.hibernate.cfg.Configuration.buildMappings(Configuration.java:988) at
org.hibernate.ejb.Ejb3Configuration.buildMappings(Ejb3Configuration.java:607) at
org.hibernate.ejb.EventListenerConfigurator.configure(EventListenerConfigurator.java:75) at
org.hibernate.ejb.Ejb3Configuration.createEntityManagerFactory(Ejb3Configuration.java:473) at
org.hibernate.ejb.Ejb3Configuration.createFactory(Ejb3Configuration.java:96) at
org.hibernate.ejb.Ejb3Configuration.createEntityManagerFactory(Ejb3Configuration.java:142) ... 14 more


Anybody know what I am missing? How do I tell it (using annotations) that the value column is a plain old string?

Thanks for any help,
Mike


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 15, 2006 10:44 am 
Regular
Regular

Joined: Sun May 08, 2005 2:48 am
Posts: 118
Location: United Kingdom
Does Hibernate support Generics ? If you remove the Generics does that change the error. Looking over my mapping I don't use Generics even when everything else I'm doing is Java5.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 15, 2006 10:59 am 
Newbie

Joined: Mon Nov 08, 2004 6:03 pm
Posts: 8
The error does change:

org.hibernate.AnnotationException: Collection has neither generic type or OneToMany.targetEntity() defined


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 15, 2006 12:02 pm 
Regular
Regular

Joined: Sun May 08, 2005 2:48 am
Posts: 118
Location: United Kingdom
How do you use annotations ? JDK5 annotation not XDoclet ? Does your IDE support them ? What IDE do you use ?
It is something I would like to start using.


The example in section 2.2.5.3.1. of the annotations docs indicate the target has to be an entity (which I guess to mean a <composite-element .. >) but I know that it doesn't since my mapping works for the situation you describe. With a composite-element another POJO is needed to represent that, this allows for getters and setters in the example to exist.

So back to your original question, how can you describe the HBM mapping I quoted with annotations ?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 15, 2006 12:06 pm 
Regular
Regular

Joined: Sun May 08, 2005 2:48 am
Posts: 118
Location: United Kingdom
Maybe someone could argue that if the type in the Generic is a boxed primitive object it should be treated differently and you get the mapping you expect just by using Map<String,String>. but if its a user-defined POJO then it works like the example states, presumably using <composite-element> in the mapping, instead of <element>.


Top
 Profile  
 
 Post subject: Probably it's not [yet] possible
PostPosted: Wed Feb 15, 2006 12:10 pm 
Newbie

Joined: Wed Feb 15, 2006 10:39 am
Posts: 6
I think, the persistence of Map of Strings is currently not possible in EJB3. When I needed something similar I used a workaround: created a simple class with key and value. Then the mapping would look like:

Code:
@OneToMany(mappedBy="parent",cascade=CascadeType.ALL, fetch=FetchType.EAGER)
@MapKey(name="groupName")
public Map<String,Node> getMyMap() {
   return myMap;
}

public class Node implements Serializable {

    private String value;

    private Long id;

    private Parent parent;

    private String groupName;



It seems that currently the key property of the map should be stored in the Value class.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 15, 2006 12:19 pm 
Newbie

Joined: Wed Feb 15, 2006 10:39 am
Posts: 6
dlmiles wrote:
The example in section 2.2.5.3.1. of the annotations docs indicate the target has to be an entity (which I guess to mean a <composite-element .. >) but I know that it doesn't since my mapping works for the situation you describe.


Well, I also had this with plain Hibernate, with no annotations, but even in this case I wouldn't recomend doing it: If you would need a HQL query using not just Map's key, but also a value, you won't be able to do it, it's just not supported.

But it's not a big deal, since you can do the same use case with a Value class.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 15, 2006 12:27 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
Hi
1. Of course Generics are supported in Hibernate Annotations
2. @MapKey has to refer to a property on the target object. This is doable for entities and composite elements but does not make sens for elements
3. pure support for Map a la Hibernate core is yet to be implemented in annotations

_________________
Emmanuel


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 10 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.