-->
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.  [ 15 posts ] 
Author Message
 Post subject: Map of primitives using CollectionOfElements
PostPosted: Wed Dec 28, 2005 1:27 pm 
Newbie

Joined: Wed Dec 28, 2005 1:18 pm
Posts: 5
I'm having some trouble understanding how the CollectionOfElements annotation works with Map.

I have an entity which contains a Map<String, Boolean> which I'd like to map without having to create an entity for the String/Boolean pair.

With XML mapping, I did:
<map name="myMap" table="TBL_MY_MAP" lazy="false" cascade="all-delete-orphan" access="field">
<key column="COL_OWNER"/>
<index column="COL_KEY" type="string"/>
<element column="COL_VALUE" type="boolean" not-null="true"/>
</map>

I have tried a number of variations of the following without luck and I don't really understand how the various annotations work together so I've ended up resorting to trial and error which isn't good nor have I stumbled across the right way to do this.

@CollectionOfElements
@JoinTable(table=@Table(name="TBL_MY_MAP),
joinColumns= {
@JoinColumn(name="COL_KEY"),
}
)
@Column(name="COL_VALUE")
private Map<String, Boolean> myMap = new HashMap<String, Boolean>();

The documentation seems to cover Sets but I am rather confused about Map. Any help and/or guidance is appreciated.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 02, 2006 6:29 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
http://opensource.atlassian.com/projects/hibernate/browse/ANN-1

_________________
Emmanuel


Top
 Profile  
 
 Post subject: with core types
PostPosted: Fri Apr 21, 2006 11:07 am 
Newbie

Joined: Tue May 25, 2004 9:56 am
Posts: 19
Emmanuel,

ANN-1 does not explain how to use a Map with core types. I haven't found anywhere that describes how to do that.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 21, 2006 11:39 am 
Newbie

Joined: Tue May 25, 2004 9:56 am
Posts: 19
Nevermind. It is explained at http://forum.hibernate.org/viewtopic.php?t=955308 and http://www.hibernate.org/329.html#A13 ("I can't map a Map")


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 27, 2006 10:14 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
this is now possible in the latest release.

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Fri Sep 22, 2006 11:19 am 
Regular
Regular

Joined: Sun Sep 26, 2004 9:27 pm
Posts: 75
Location: Atlanta, GA, USA
Would someone please post an example of the use of the annotations?

I need to store Map<Integer, Integer> and am having trouble.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 02, 2006 1:09 pm 
Regular
Regular

Joined: Sun Sep 26, 2004 9:27 pm
Posts: 75
Location: Atlanta, GA, USA
lukasbradley wrote:
Would someone please post an example of the use of the annotations?

I need to store Map<Integer, Integer> and am having trouble.


Gavin will give a massage to whomever answers this question.


Top
 Profile  
 
 Post subject: Map of primitives using CollectionOfElements
PostPosted: Tue Nov 07, 2006 11:10 am 
Newbie

Joined: Thu Jul 20, 2006 6:25 pm
Posts: 6
I've been searching the documentation, the example code and this forum and have found the instructions a little unclear. I've tried gluing together the various hints in different ways, and eventually found my way toward this:

Code:
@CollectionOfElements(fetch=FetchType.EAGER)
@JoinTable(
    name = "MappingTable",
    joinColumns = @JoinColumn(name = "mapOwner"))
@Column(
   name = "mapValueItem",
   nullable = false

@org.hibernate.annotations.MapKey(
    columns={
        @Column(
             name="mapKeyItem"
        )
   }
)
protected Map<String, String> getMapping() {
    return mapping_;
}


This appears to generate the correct queries and behavior for my purposes.


I had tried the seemingly obvious javax.persistence.MapKey annotation, but ended up with the error:
Quote:
org.hibernate.AnnotationException: Associated class not found: java.lang.String

which did not help me in diagnosing the problem.

Eventually I found this hint in the API documentation for org.hibernate.annotations.MapKey:
Quote:
Define the map key columns as an explicit column holding the
map key This is completly different from MapKey which use an
existing column This annotation and MapKey are mutually exclusive



If the above annotation is incorrect or misguided in any way, please say so.

Thanks,
Nate

_________________
Nate Franzen


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 10, 2006 4:08 pm 
Regular
Regular

Joined: Sun Sep 26, 2004 9:27 pm
Posts: 75
Location: Atlanta, GA, USA
lukasbradley wrote:
lukasbradley wrote:
Would someone please post an example of the use of the annotations?

I need to store Map<Integer, Integer> and am having trouble.


Gavin will give a massage to whomever answers this question.


Gavin, you owe me a massage.

And I'm uber-fantastic, so I edited the message to remove my other question.

Code:
   @CollectionOfElements
   @JoinTable(name="MyObjectClockUsage", joinColumns={@JoinColumn(name="myObjectId")})
   @org.hibernate.annotations.MapKey(columns={@Column(name="position")})
   @Column(name="timeInMillis", nullable=false, columnDefinition="INTEGER UNSIGNED")   
   private Map<Integer, Integer>   clockUsage   = new HashMap<Integer, Integer>();


Top
 Profile  
 
 Post subject: But how about Map<Entity, AnotherEntity>?
PostPosted: Wed Nov 15, 2006 11:02 pm 
Newbie

Joined: Wed Nov 15, 2006 10:53 pm
Posts: 2
I would like to get the following to work...

class EntityA {

@OneToMany
@MapKey(name="entityB")
Map<EntityB, EntityC> entityCs;

}

EntityC represents a join between EntityA and EntityB with various additional attributes. The value of MapKey is the name of the property that points to an EntityB in the EntityC join table. The combination of EntityA and EntityB is unique in the table representing EntityC. However, I only ever seem to get one row appear in my Map.

If I instead use List<EntityC> it all works fine, apart from having to iterate over the EntityC's to find the one that maps to EntityB.

It seems that only primitive types can be used as the key? Or at least if it is possible there are no examples demonstrating this using annotations that I have been able to track down.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Nov 23, 2006 1:02 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
It works.
Check org.hibernate.test.annotations.indexcoll.AddressBook.directoryEntries

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Thu Nov 23, 2006 7:47 pm 
Newbie

Joined: Wed Nov 15, 2006 10:53 pm
Posts: 2
Hi Emmanuel,

Thanks for your pointer. I have looked at the example in AddressBook, and directoryEntries does indeed appear to map the relationship in the same way we are aiming to achieve. However I note that the AddressBook.getDirectoryEntries() method is never called by the org.hibernate.test.annotations.indexcoll.IndexedCollectionTest , at least in the current revisions that I am able to browse via http://anonsvn.jboss.org/, and my summary attempts to get this working in my own code have continued to fail.

In my case (continuing my previous example), the first call to the containsKey method in my following example returns true...

Code:
class EntityA {
  @OneToMany
  @MapKey(name="entityB">
  Map<EntityB, EntityC> entityCs = new HashMap<EntityB, EntityC>();

  boolean containsKey(EntityB entityB) {
    return entityCs.containsKey(entityB1);
  }
}



However, calling it a second time with a different instance of entityB which exists in a valid relationship causes it to return false, when it really should return true.

It appears that the first call to a method on the Map (in my example, Map.containsKey() ) triggers a db query, and the return value indicates that the Map does indeed contain the key. However the second call to Map.containsKey() for another valid key in a valid relationship returns false.

If I use a list instead, and do a list traversal, everything works fine...

Code:
class EntityA {

  @OneToMany
  List<EntityC> entityCs = new ArrayList<EntityC>();

  boolean containsKey(EntityB entityB) {
    for(EntityC entityC : entityCs) {
      if (entityC.getEntityB().equals(entityB)) {
        return true;
      }
    }
    return false;
  }
}


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 28, 2006 1:28 pm 
Newbie

Joined: Wed Jul 05, 2006 3:09 am
Posts: 3
lukasbradley wrote:
Code:
   @CollectionOfElements
   @JoinTable(name="MyObjectClockUsage", joinColumns={@JoinColumn(name="myObjectId")})
   @org.hibernate.annotations.MapKey(columns={@Column(name="position")})
   @Column(name="timeInMillis", nullable=false, columnDefinition="INTEGER UNSIGNED")   
   private Map<Integer, Integer>   clockUsage   = new HashMap<Integer, Integer>();


This uses the columnDefinition to specify the type of the column for the value.

I tried to use the @Type annotation to specify type="text" for a string. That works fine at build time with the hibernate tools (generate the correct table definition sql), unfortunately, I get a ClassCastException at runtime:
Code:
    [junit] java.lang.ClassCastException: org.comp.MyEnumUsedAsKey
    [junit]     at org.hibernate.type.TextType.toString(TextType.java:71)
    [junit]     at org.hibernate.type.NullableType.nullSafeSet(NullableType.java:87)
    [junit]     at org.hibernate.type.NullableType.nullSafeSet(NullableType.java:60)


Does anybody knows if this should be supported or what I'm doing wrong?

The mapping is the following:
Code:
    @CollectionOfElements
    @JoinTable( name="my_table" )
    @Cascade(value = org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
    @Enumerated(value=EnumType.STRING)
    @org.hibernate.annotations.MapKey( columns = { @Column( name="my_enum" ) } )
    @Column( name="my_value" )
    @Type( type="text" )
    public Map<MyEnumTypeUsedAsKey, String> getMappedValues() {
        return _mappedValues;
    }


Thanx in advance,
cheers,
Martin


Top
 Profile  
 
 Post subject:
PostPosted: Mon Dec 04, 2006 4:33 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
Sorry jimmcslim, I've added some more tests and they work fine. contains use equals/hashCode, be careful with your implementation

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Sun Dec 24, 2006 3:08 pm 
Beginner
Beginner

Joined: Fri Jun 09, 2006 4:21 pm
Posts: 23
Location: Reading
Hi,

The following mapping produces both PK and INDEX set on transaction_id column.

Is it supposed to be like that? phpMyAdmin gives warning about PK and INDEX set on the same column.

Code:
@CollectionOfElements(fetch = FetchType.EAGER)
    @JoinTable(
            name = "namespaces",
            joinColumns = @JoinColumn(name = "transaction_id")
    )
    @org.hibernate.annotations.MapKey(
            columns = @Column(name = "ns_prefix")
    )
    @Column(name = "ns_uri", nullable = false)
    private Map<String, String> namespaces = new HashMap<String, String>();


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 15 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.