-->
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.  [ 8 posts ] 
Author Message
 Post subject: Saving a HashMap field of a pojo
PostPosted: Thu Nov 08, 2007 9:22 pm 
Newbie

Joined: Thu Nov 08, 2007 8:02 pm
Posts: 9
Hy everybody,
I would like save an annotated pojo to the database which has a Map property that looks like this:

Code:
private Map<String, String> settings;


Now I've read that you can do this by using a mapping like this:

Code:
<map role="ages">
<key column="id"/>
<index column="name" type="string"/> 
<element column="age" type="string"/> 
</map>


But I want to use annotations instead, so I began to look for examples.
If I use:

Code:
   @OneToMany(mappedBy="value")
   @MapKey(name="keyvalue")
   public Map<String, String> getSettings() {
      return settings;
   }

I get an exception telling me that

Code:
Invocation of init method failed; nested exception is org.hibernate.AnnotationException:
Use of @OneToMany or @ManyToMany targeting an unmapped class:
com.xyz.core.impl.collector.AbstractCollector.settings[java.lang.String]


"value" and "keyvalue" are just random names - intended to be used as column names. Should there be specific names of fields instead?

Any suggestions on what I'm doing wrong?

Hibernate version:3.3.0.ga

p.s.: I also read about dynamic entity mode - this is NOT what I'm going for here. I want to map my HashMap field of my pojo to a database table - that's all.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 09, 2007 6:10 am 
Expert
Expert

Joined: Fri Jul 13, 2007 8:18 am
Posts: 370
Location: london
Code:
@CollectionOfElements
public Map<String, String> getSettings() {
      return settings;
}


There are ways to override table and column names if necessary. See "2.4.6.2.5. Collection of element or composite elements" in hibernate annotations docs.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 09, 2007 9:04 am 
Newbie

Joined: Thu Nov 08, 2007 8:02 pm
Posts: 9
Thank you! But that seems to work only for the basic circumstances.
If I do this on MySQL 5.0 i get
Code:
+--------------+--------------+
| Field        | Type         |
+--------------+--------------+
| Collector_id | bigint(20)   |
| element      | varchar(255) |
| mapkey       | varchar(255) |
+--------------+--------------+


What I actually needed was a Text type (a Clob in Oracle speak).
So if I try this mapping:

Code:
@CollectionOfElements
@AttributeOverride(name="element.value", column=@Column(columnDefinition="TEXT"))
public Map<String, String> getSettings() {
      return settings;
}


I get this exception:
Code:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in file [C:\Users\tag\workspace\xyz\conf\applicationContext.xml]: Invocation of init method failed; nested exception is org.hibernate.PropertyNotFoundException: Could not find a setter for property bytes in class java.lang.String
Caused by: org.hibernate.PropertyNotFoundException: Could not find a setter for property bytes in class java.lang.String
   at org.hibernate.property.BasicPropertyAccessor.createSetter(BasicPropertyAccessor.java:216)
   at org.hibernate.property.BasicPropertyAccessor.getSetter(BasicPropertyAccessor.java:209)
   at org.hibernate.mapping.Property.getSetter(Property.java:277)
   at org.hibernate.tuple.component.PojoComponentTuplizer.buildSetter(PojoComponentTuplizer.java:137)
   at org.hibernate.tuple.component.AbstractComponentTuplizer.<init>(AbstractComponentTuplizer.java:44)
   at org.hibernate.tuple.component.PojoComponentTuplizer.<init>(PojoComponentTuplizer.java:38)
   at org.hibernate.tuple.component.ComponentEntityModeToTuplizerMapping.<init>(ComponentEntityModeToTuplizerMapping.java:52)
   at org.hibernate.tuple.component.ComponentMetamodel.<init>(ComponentMetamodel.java:50)
   at org.hibernate.mapping.Component.buildType(Component.java:152)
   at org.hibernate.mapping.Component.getType(Component.java:145)
   at org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:253)
   at org.hibernate.mapping.Collection.validate(Collection.java:278)
   at org.hibernate.mapping.IndexedCollection.validate(IndexedCollection.java:67)
   at org.hibernate.cfg.Configuration.validate(Configuration.java:1106)
   at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1287)
   at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:915)


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 09, 2007 10:03 am 
Expert
Expert

Joined: Fri Jul 13, 2007 8:18 am
Posts: 370
Location: london
That seems a little odd.
There's an article about using a custom type to wrap/unwrap clobs as strings. However, its for hibernate v1 - I expect you shouldn't need to do this anymore:
http://www.hibernate.org/76.html

What happens if you add a text field to the parent class? Do you get the same exception? i.e. is it related to CollectionOfElements rather than a specific clob or mysql problem?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 09, 2007 2:11 pm 
Newbie

Joined: Thu Nov 08, 2007 8:02 pm
Posts: 9
No, it seems alright if I use

Code:
   @Column(length=4096)
   public String getTestField() {
      return testField;
   }


The field gets created as "text" type.

If I try this one:

Code:
   @AttributeOverride(name="element.testField", column=@Column(columnDefinition="TEXT"))
   public String getTestField() {
      return testField;
   }


it gets ignored though and I get "varchar(256)" again.

If I try
Code:
   @CollectionOfElements
   @AttributeOverride(name="element.settings.key", column=@Column(length=4096))
   public Map<String, String> getSettings() {
      return settings;
   }


I get the same exception as above.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 13, 2007 4:43 pm 
Newbie

Joined: Thu Nov 08, 2007 8:02 pm
Posts: 9
Whoa, there seems to be some kind of limitation to what you can do with yout index column. Turns out this problem is not restricted to Annotation behaviour.

If you do:

Code:
      <map name="settings" >
         <key column="id" />
         <index column="keyValue" type="string" length="255"/>
         <element column="value" type="string" length="1024" />
      </map>


you get a Table that looks perfectly okay:
Code:
mysql> desc  testentity_settings;
+----------+--------------+------+-----+---------+-------+
| Field    | Type         | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+-------+
| id       | bigint(20)   | NO   | PRI |         |       |
| value    | text         | YES  |     | NULL    |       |
| keyValue | varchar(255) | NO   | PRI |         |       |
+----------+--------------+------+-----+---------+-------+


However if you decide you want a text field as your index column:

Code:
      <map name="settings" >
         <key column="id" />
         <index column="keyValue" type="string" length="1024"/>
         <element column="value" type="string" length="1024" />
      </map>


The DDL Creation fails and everything just dies. This is not doumented behaviour as far as I know.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 14, 2007 12:43 pm 
Expert
Expert

Joined: Fri Jul 13, 2007 8:18 am
Posts: 370
Location: london
Its a limitation of the database. You can't index a LOB field (on oracle at least).


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 14, 2007 1:23 pm 
Newbie

Joined: Thu Nov 08, 2007 8:02 pm
Posts: 9
I see the point in this. InnoDB isnt capable of doing fulltext indices at all. It would have been nice though to allow the developer to dismiss using the table index and instead have the map loaded into memory or use a full table scan. This would work at least reasonably well with small tables.

Thanks for clearing that up though. I appreciate your answering this.


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