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.  [ 3 posts ] 
Author Message
 Post subject: Problem with ordered list mapping
PostPosted: Tue Dec 09, 2008 10:03 am 
Newbie

Joined: Tue Dec 09, 2008 9:47 am
Posts: 2
So, I'm migrating an application from Hibernate 3.2.6.ga to Core 3.3.1.GA
and Annotations 3.4.0.GA, largely so we can use annotations and move away from mapping files. I have a bidirectional one to many relationship where the many side has a sequence number column that serves as the index for an ordered list. The sequence numbers should start with 1 in the database, so I've set the base = 1 accordingly. Here's the one side:

Code:
   
@OneToMany(fetch = FetchType.EAGER)
@JoinColumn(name = "profile_template_id", nullable = false, updatable = false)
@IndexColumn(name = "sequence_num", base = 1)
@Cascade({CascadeType.ALL, CascadeType.DELETE_ORPHAN})
public List<ProfileTemplateProperty> getProperties() {
        return this.properties;
}


and the many side:

Code:
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "profile_template_id", nullable = false, insertable = false, updatable = false)
public ProfileTemplate getProfileTemplate() {
        return this.profileTemplate;
}


The problem is that although the index column gets inserted, it doesn't seem to obey the base = 1 (meaning it starts the index at 0 in the db). Therefore, when I turn around and read the entity back out, Hibernate tries to shift the index down and throws an IndexOutOfBoundsException:
Code:
java.lang.ArrayIndexOutOfBoundsException: -1
   at java.util.ArrayList.set(ArrayList.java:339)
   at org.hibernate.collection.PersistentList.readFrom(PersistentList.java:409)
   at org.hibernate.loader.Loader.readCollectionElement(Loader.java:1031)
   at org.hibernate.loader.Loader.readCollectionElements(Loader.java:669)
   at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:614)
   at org.hibernate.loader.Loader.doQuery(Loader.java:724)
   at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:259)
   at org.hibernate.loader.Loader.loadCollection(Loader.java:2015)
   at org.hibernate.loader.collection.CollectionLoader.initialize(CollectionLoader.java:59)
   at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:587)
   at org.hibernate.event.def.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:83)
   at org.hibernate.impl.SessionImpl.initializeCollection(SessionImpl.java:1743)
   at org.hibernate.collection.AbstractPersistentCollection.forceInitialization(AbstractPersistentCollection.java:476)
   at org.hibernate.engine.StatefulPersistenceContext.initializeNonLazyCollections(StatefulPersistenceContext.java:867)
   at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:264)
   at org.hibernate.loader.Loader.doList(Loader.java:2228)
   at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2125)
   at org.hibernate.loader.Loader.list(Loader.java:2120)
   at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:401)
   at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:361)
   at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:196)
   at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1148)
   at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102)
   at org.hibernate.impl.AbstractQueryImpl.uniqueResult(AbstractQueryImpl.java:835)
   at com.novarra.profiling.dao.generic.GenericDAOHibernateImpl.executeLookup(GenericDAOHibernateImpl.java:96)
   at com.novarra.profiling.dao.generic.finder.FinderIntroductionInterceptor.invoke(FinderIntroductionInterceptor.java:28)
   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
   at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
   at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
   at $Proxy29.lookupByName(Unknown Source)
   at com.novarra.profiling.integration.dao.ProfileIntegrationTest.clean(ProfileIntegrationTest.java:39)
   at com.novarra.profiling.integration.dao.ProfileIntegrationTest.onTearDown(ProfileIntegrationTest.java:34)
   at org.springframework.test.AbstractSingleSpringContextTests.tearDown(AbstractSingleSpringContextTests.java:137)
   at org.springframework.test.ConditionalTestCase.runBare(ConditionalTestCase.java:76)
   at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:40)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
   at com.intellij.rt.execution.application.AppMain.main(AppMain.java:90)


My database schema has not changed, and this worked under Hibernate 3.2.6.ga with mapping files. Here's the mapping we were using previously:

One side:
Code:
        <list name="properties" lazy="false" cascade="all-delete-orphan">
            <key column="profile_template_id" not-null="true"/>
            <list-index column="sequence_num" base="1"/>
            <one-to-many class="ProfileTemplateProperty"/>
        </list>


Many side:
Code:
        <many-to-one name="profileTemplate" class="ProfileTemplate" column="profile_template_id" not-null="true" insert="false" update="false"/>


In case it's relevant, we're using MySQL 5.0. I did a search and saw similar questions asked a couple of times but never answered. Thanks in advance.


Top
 Profile  
 
 Post subject: Solved
PostPosted: Tue Dec 09, 2008 1:42 pm 
Newbie

Joined: Tue Dec 09, 2008 9:47 am
Posts: 2
Ok I fixed this. Apparently the "updatable = false" on the one side was the problem, the corrected code is below. While obviously this was my fault, I will say that Hibernate should provide better messages in this instance. From my research, it seems there is exactly one way to make this work right, and about a gazillion that fail in one way or another. I'd think that there could be some better detection of invalid configuration here rather than simply limping along until you get an ArrayIndexOutOfBounds exception.


Code:
@OneToMany(fetch = FetchType.EAGER)
@JoinColumn(name = "profile_template_id", nullable = false)
@IndexColumn(name = "sequence_num", base = 1)
@Cascade({CascadeType.ALL, CascadeType.DELETE_ORPHAN})
public List<ProfileTemplateProperty> getProperties() {
        return this.properties;
}


Top
 Profile  
 
 Post subject: Re: Problem with ordered list mapping
PostPosted: Tue Jul 28, 2009 2:05 pm 
Newbie

Joined: Tue Jul 28, 2009 1:43 pm
Posts: 1
This solution works but Hibernate will produce some redundant update statements:
insert into parent...
insert into child...
update child set parent_id = ?, index = ? where id = ? -- for each child item

My solution is to remove "base = 1":
Code:
@OneToMany
@JoinColumn(name = "mms_message_id", nullable = false, insertable = false, updatable = false)
@IndexColumn(name="order_number")

Maybe it will help someone.


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