-->
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.  [ 16 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: ClassCastException in sorted Set
PostPosted: Sat Jul 17, 2004 11:19 pm 
Newbie

Joined: Sat Jul 17, 2004 2:35 pm
Posts: 4
OK. I am trying to provide some sorting for collections which result from many-to-many relationships. I have seen previous posts which suggest that the DB "order-by" attribute of a collection mapping does not apply to objects in the "child" half of a M2M relationship, and that this behaviour is "not supported" (this is a little irritating actually). So, as a second choice, I have opted for in-memory sorting by ensuring all my persistent objects are Comparable. Initially I was using the "bag" collection type, simply because I am used to refering to Lists, but the list mapping requires an index column with "sequential integers numbered from zero", which I don't have (who does btw?).

So.. I have ended up using a Set as the type for all my collections. Now... I don't really want to change all of my persistent classes so that they identify collections as Sets (they currently identify them as simple Collections), but when I try to save an object in a Hibernate session, I get the following error:

Code:

java.lang.ClassCastException
   at net.sf.hibernate.type.SortedSetType.wrap(SortedSetType.java:31)
   at net.sf.hibernate.impl.WrapVisitor.processArrayOrNewCollection(WrapVisitor.java:78)
   at net.sf.hibernate.impl.WrapVisitor.processCollection(WrapVisitor.java:49)
   at net.sf.hibernate.impl.AbstractVisitor.processValue(AbstractVisitor.java:69)
   at net.sf.hibernate.impl.WrapVisitor.processValues(WrapVisitor.java:93)
   at net.sf.hibernate.impl.SessionImpl.flushEntity(SessionImpl.java:2488)
   at net.sf.hibernate.impl.SessionImpl.flushEntities(SessionImpl.java:2454)
   at net.sf.hibernate.impl.SessionImpl.flushEverything(SessionImpl.java:2256)
   at net.sf.hibernate.impl.SessionImpl.flush(SessionImpl.java:2235)



Now, SortedSetType.java:31 looks like this:

Code:
return new SortedSet( session, (java.util.SortedSet) collection );


Surely Hibernate does not expect me to actually use a SortedSet all the way up in my application?? The documentation states:

"Java type of a property holding a collection must be the interface type (ie. Map, Set or List; never HashMap, TreeSet or ArrayList)."

So.. I reluctantly changed all my Collection references to Set references, but because the runtime type of the Set is NOT a SortedSet, I still get this error.

I must be doing something wrong here.. I cannot accept that Hibernate is forcing me to implement Collections with specific Java types!

Not very OO, or very AO for that matter.

Please help!

P.S I am using Hibernate 2.1.4 with MS SQL Server 2000. An example set mapping is below

Code:

<set name="groups" table="PersonGroup" lazy="false" sort="natural">
    <key column="personId"/>
    <many-to-many column="groupId" class="Group"/>
</set>   



Top
 Profile  
 
 Post subject: Re: ClassCastException in sorted Set
PostPosted: Sun Jul 18, 2004 12:49 am 
Senior
Senior

Joined: Sat Jul 17, 2004 5:16 pm
Posts: 143
jasonpolites wrote:
The documentation states:

"Java type of a property holding a collection must be the interface type (ie. Map, Set or List; never HashMap, TreeSet or ArrayList)."



It sounds like your problem is a Java problem and not a Hibernate problem. The type of the class is a Hibernate type, which is an implementation of Set. And "SortedSet" is an interface which is a subinterface of Set. So how can you typecast one to the other in Java??? It is not possible. Thus you need to make a loop to get your elements out and put them into a sortedset (which is an interface, so use a class that implements it e.g. TreeSet).

Chris


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jul 18, 2004 1:34 am 
Newbie

Joined: Sat Jul 17, 2004 2:35 pm
Posts: 4
ok, my problem isn't how to avoid the error. Clearly if I use a SortedMap type as my collection this error will dissappear. The problem is that I am astounded that Hibernate forces me to do this.

The mere fact that the documentation stipulates that your objects should house interface types (Map, Set etc), but there is a "hidden" rule that says that the runtime type of this must adhere to some internal hibernate logic, breaks all we know about Object Orientation.

Imagine you had some for of abstract class which, because Hibernate says it has to, contains a Set of child objects. You instruct a developer to extend this abstract class if they want it persisted. There is no way for that developer to know that the runtime type of the Set should be a SortedSet. The defeats the whole purpose of having a class hierarchy.

I recently watched a presentation by Mark Fleury (Jboss) about Aspect Oriented Programming and how Hibernate is able to provide a persistence "aspect" via annotation of POJO (Plain Old Java Objects).

This SortedSet issue is neither object oriented, nor is it an aspect that allows for the use of plain java objects.

Someone please tell me I am wrong here!


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jul 18, 2004 1:49 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
What on earth are you on about here???

Perhaps you need to spend some time learning the Java2 collections framework.

The contract for Set does NOT provide any ordering. So, if you expect ordering, you must use a SortedSet.

This is Java that is "forcing" you to do this, it is certainly not Hibernate specific.

Now, it should be blindingly obvious that this does not in any way constrain the type of a variable or property that points to the SortedSet: it could be SortedSet, Set, Object, whatever. But when you actually *instantiate* the SortedSet, it *clearly* must implement the SortedSet interface, otherwise it has no ordering at all. So you should, for example, instantiate a TreeSet.

And to plan for extension, it is just trivial: declare the property of type SortedSet. Done. Finished.

And please don't try to rudely lecture us about OOP/AOP/whatever, just because you have some problems understanding trivial shit.

Honestly....


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jul 18, 2004 3:44 am 
Newbie

Joined: Sat Jul 17, 2004 2:35 pm
Posts: 4
Well. I must say I am a little disappointed by this response from the Hibernate team. At no time was I attempting to lecture anyone, and in-fact indicated that I needed help in understanding the idiosyncrasies of Hibernate, and indicated that I wished to be told that I was wrong.

I do not recall asking to be abused, or ridiculed for my queries.

As for my understanding of Java2 and collections, it seems to me that whilst a Set does not implicitly define any ordering, the collection's framework DOES allow a Collection of Comparable objects to be sorted.

The sorting in a SortedSet is done via either a Comparator, or the Comparable interface, so it seems to me that it should make little difference to Hibernate whether the collection is a SortedSet, or any other type of collection.

Furthermore, the overhead in executing "ordered" inserts into a set is often unnecessary when performing database inserts, and is most often only relevant during selects. This it would make more sense to provide for Collections which *can* be sorted but which don't necessarily enforce a contract as such.

I see this as a limitation of Hibernate, NOT Java. Having said that, I do believe Hibernate to be an amazing step forward in the way objects map to relational structures, and despite a few oddities has saved me an enormous amount of time.

All I was looking for was a "no.. it's not supported, but you can achieve your result like this...". I most certainly was NOT expecting the childish and intolerant response I was given.

If you don't have anything constructive to say.. why bother?


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jul 18, 2004 3:58 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Christian, please ban this person.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jul 18, 2004 4:06 am 
Newbie

Joined: Sat Jul 17, 2004 2:35 pm
Posts: 4
Are you serious?

Can you please explain why?


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jul 18, 2004 4:15 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
I am dead serious.

Why? Because:

(1) you are completely, off the planet, wrong
(2) this was explained to you very politely
(3) you responded by insulting us, instead of taking the polite advice and thinking it over carefully, and realizing your mistake
(4) I explained less politely
(5) you insulted me *again*

This is the free support forum. You are begging charity by posting here.

If you want to be noisy and insulting, you can post on TSS. Tell 'em all how "childish" and "intolerant" I am, they'll all love it. But you won't do it here.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jul 18, 2004 10:45 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Damn, I can be *really* short-tempered late at night.

Sorry if I misread your initial post as being more negative than you perhaps intended.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jul 18, 2004 11:05 am 
Senior
Senior

Joined: Sat Jul 17, 2004 5:16 pm
Posts: 143
gavin wrote:
Damn, I can be *really* short-tempered late at night.

Sorry if I misread your initial post as being more negative than you perhaps intended.


No, you were completely not out-of-line (inline?) :). This user is belligerent about things he doesnt know about. Which is not acceptable behavior, especially when this is a free support forum and the Hibernate developers are spending time to personally respond (which is very impressive by the way). I had a more aggressive post at first, which I decided to make more diplomatic just to give the user another chance. But the user continued to be a complete ass.

How did he get his name "polites"? Is that like when you call a fat guy "slim"? :)

Chris


Top
 Profile  
 
 Post subject: Re: ClassCastException in sorted Set
PostPosted: Wed Sep 08, 2004 6:00 pm 
Newbie

Joined: Wed Sep 08, 2004 5:09 pm
Posts: 2
I've run into the same problem the first user had. I have a VoteDescription class which represents a poll, and a collection of VoteResults which correspond to the opinions in the poll. When a user votes to one opinion , I want to update the count to that opioion. I am using the HibernateTransactionManager to manage the transaction.

Bean definitions in ApplicationContext.xml:

<bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
<property name="dataSource"><ref bean="dataSource"/></property>
<property name="mappingResources">
<list>
...
</list>
</property>
</bean>

<bean id="transactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager">
<property name="sessionFactory"><ref local="sessionFactory"/>
</property>
</bean>


Java code to do the database update:

public void recordUserVote(final long voteId, final long voteOptionId) {
//voteId: id of the poll; optionId: id of the opinion
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
public void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
VoteResults voteResults = new VoteResults(voteOptionId);
voteResults = voteResultsDao.retrieveVoteResutls(voteResults);
long newResult = voteResults.getVoteResult() + 1;
voteResults.setVoteResult(newResult);
voteResultsDao.saveVoteResults(voteResults);
}
});
}


Mapping files:

<class
name="cfr.domain.VoteDescription"
table="cfr_vote_desc"
...
>

<id
name="voteId"
column="vote_id"
type="long"
>
<generator class="native">
</generator>
</id>
<set
name="voteResults"
table="cfr_vote_results"
lazy="true"
inverse="true"
cascade="none"
>

<key
column="vote_id"
>
</key>

<one-to-many
class="cfr.domain.VoteResults"
/>
</set>
....
</class>

<class
name="cfr.domain.VoteResults"
table="cfr_vote_results"
...
>

<id
name="voteOptionId"
column="vote_option_id"
type="long"
>
<generator class="native">
</generator>
</id>

<property
name="voteId"
type="long"
update="true"
insert="true"
access="property"
column="vote_id"
not-null="true"
/>
</class>


Stack trace:

at net.sf.hibernate.type.SortedSetType.wrap(SortedSetType.java:31)
at net.sf.hibernate.impl.WrapVisitor.processArrayOrNewCollection(WrapVisitor.java:78)
at net.sf.hibernate.impl.WrapVisitor.processCollection(WrapVisitor.java:49)
at net.sf.hibernate.impl.AbstractVisitor.processValue(AbstractVisitor.java:69)
at net.sf.hibernate.impl.WrapVisitor.processValues(WrapVisitor.java:93)
at net.sf.hibernate.impl.SessionImpl.flushEntity(SessionImpl.java:2488)
at net.sf.hibernate.impl.SessionImpl.flushEntities(SessionImpl.java:2454)
at net.sf.hibernate.impl.SessionImpl.flushEverything(SessionImpl.java:2256)
at net.sf.hibernate.impl.SessionImpl.flush(SessionImpl.java:2235)
at net.sf.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:61)
at org.springframework.orm.hibernate.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:386)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:316)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:126)
at cfr.business.PostServiceImpl.recordUserVote(PostServiceImpl.java:173)
at cfr.actions.PostActionDispatcher.vote(PostActionDispatcher.java:180)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at org.apache.struts.actions.DispatchAction.dispatchMethod(DispatchAction.java:280)
at org.apache.struts.actions.DispatchAction.execute(DispatchAction.java:216)
at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:484)
at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:274)
at edu.iu.uis.cfr.controllers.ForumController.process(ForumController.java:53)
at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1482)
at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:525)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:709)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:237)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:157)
at edu.iu.uis.cas.filter.FilterCAS.doFilter(FilterCAS.java:238)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:186)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:157)
at org.springframework.orm.hibernate.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:117)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:73)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:186)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:157)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:214)
at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
at org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java:198)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:152)
at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:137)
at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:102)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:929)
at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:160)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:799)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:705)
at org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java:577)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:683)
at java.lang.Thread.run(Thread.java:534)


I'm using Oracle 9i.


Thanks for your help.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Sep 08, 2004 8:26 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
The voteResults property must always contain an instance of SortedSet.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 09, 2004 10:21 am 
Newbie

Joined: Wed Sep 08, 2004 5:09 pm
Posts: 2
gavin wrote:
The voteResults property must always contain an instance of SortedSet.


Could you elaborate a little more on that? i.e. where do I create an instance of SortedSet and how do I use it? Why do I need to do it even if I'm not interested in the ordering of voteREsults?

Thanks.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 08, 2005 11:48 pm 
Newbie

Joined: Wed Jan 26, 2005 10:17 pm
Posts: 8
Hi,
I'm sorry to bother you, nut I could really do with some ( moral ) support.

I am strugging with a composite-id class mapping, or at least I think that might have somthing to do with it.

These are the debug lines:

00:07:31,704 DEBUG DefaultLoadEventListener:307 - resolved object in session cache: [chances.hibernate.LstNivelIdioma#4]
00:07:31,704 DEBUG TwoPhaseLoad:159 - done materializing entity [chances.hibernate.CndIdioma#2]
00:07:31,704 DEBUG PersistenceContext:719 - 1 collections were found in result set
java.lang.ClassCastException: chances.hibernate.CndIdioma
at java.util.TreeMap.compare(TreeMap.java:1093)
at java.util.TreeMap.put(TreeMap.java:465)
at java.util.TreeSet.add(TreeSet.java:210)
at java.util.AbstractCollection.addAll(AbstractCollection.java:318)
at java.util.TreeSet.addAll(TreeSet.java:258)
at org.hibernate.collection.PersistentSet.endRead(PersistentSet.java:237)

So it seems to be doing allright loading the object for the collection, but then something happens when adding the objects to the collection.

My problem is that the cast error is not thrown in my ( hibernate ) class, but in the TreeMap class...

Does anyone have an idea. Would it be usefull to post more details?

Here comes the mping of the mentioned chances.hibernate.CndIdioma class:

<hibernate-mapping
default-cascade="save-update"
default-lazy="false">
<!--
Auto-generated mapping file from
the hibernate.org cfg2hbm engine
-->
<class
name="chances.hibernate.CndIdioma"
table="cnd_idioma"
schema="public"
>
<composite-id name="id" class="chances.hibernate.CndIdiomaId" >
<key-many-to-one name="CndPessoal" class="chances.hibernate.CndPessoal">
<column name="id_candidato" length="4" not-null="true" />
</key-many-to-one>
<key-many-to-one name="LstIdioma" class="chances.hibernate.LstIdioma">
<column name="id_idioma" length="2" not-null="true" />
</key-many-to-one>
</composite-id>

<many-to-one
name="LstNivelIdiomaLei"
class="chances.hibernate.LstNivelIdioma"
>
<column name="id_nivel_idioma_lei" length="2" not-null="false" />
</many-to-one>

<many-to-one
name="LstNivelIdiomaConv"
class="chances.hibernate.LstNivelIdioma"
>
<column name="id_nivel_idioma_conv" length="2" not-null="false" />
</many-to-one>

<many-to-one
name="LstNivelIdiomaRed"
class="chances.hibernate.LstNivelIdioma"
>
<column name="id_nivel_idioma_red" length="2" not-null="false" />
</many-to-one>



</class>
</hibernate-mapping>


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 09, 2005 7:49 am 
Newbie

Joined: Wed Jan 26, 2005 10:17 pm
Posts: 8
Me again,

I am so sorry.

I found my problem.

If you want to use the sort="natural" property on a set, you need to implement "comparable" in the associated class.

Of course this is in the documentation.

I had actually allready done that on one of my other classes.

So this was plain stupidity of me.

Sorry for wasting yor time.

Greetings from Brazil


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 16 posts ]  Go to page 1, 2  Next

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.