-->
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.  [ 2 posts ] 
Author Message
 Post subject: natural-id ArrayIndexOutOfBounds after session.flush
PostPosted: Sun Jan 22, 2006 8:39 pm 
Newbie

Joined: Sun Jan 22, 2006 7:07 pm
Posts: 2
Location: United Kingdom, Staffordshire
I have spent a week of evenings attempting to resolve what I thought would be an error in my mapping file. I finally decided to stop using a natural-id on my User entity and would just QBE with just the username set and set update="false" for the property mapping.

I decided to step through the hibernate code for the checkNaturalId and found that when there was no loaded state a "snapshot" of my entity would be retrieved and the updateable field array would start with my version field (Integer) and I have just tried to map my version field as a Long.

if ( !types[prop].isEqual( current[prop], loaded[prop], entityMode ) ) {

prop = 1

where current[1] = peterneil
and
loaded[0] = peterneil

therefore loaded[1] is the casuse of the ArrayIndex...Exception

My only work around so far is not to have a versioned entitiy with a natural-id.

Hibernate version:3.1 or 3.1.1

Mapping documents :
<class name="com.terramorph.ulm.model.User" table="app_user">
<cache usage="read-write"/>
<id name="id" column="user_id" type="java.lang.Long" unsaved-value="null">
<generator class="increment"></generator>
</id>
<natural-id mutable="false">
<property name="username" length="55" insert="true" update="false" column="username" not-null="true" unique="true"/>
</natural-id>
<!--
<version name="version" column="version" type="java.lang.Integer" unsaved-value="null" access="field" insert="true"/>
-->



Code between sessionFactory.openSession() and session.close():
... protected List<T> findByCriteria(final boolean cacheable, final boolean unique, final Criterion... criterion) {
List<T> resultList = new ArrayList<T>();
resultList = getHibernateTemplate().executeFind(
new HibernateCallback() {
public List<T> doInHibernate(Session session) throws HibernateException, SQLException {
Criteria crit = session.createCriteria(getPersistentClass());
for (Criterion c : criterion) {
crit.add(c);
}
if(cacheable){
crit.setCacheable(cacheable);
}
if (unique) {
crit.uniqueResult();
}
return crit.list();
}
});
return resultList;
}
...
public T makePersistent(T entity) {
getHibernateTemplate().saveOrUpdate(entity);
return entity;
}



Full stack trace of any exception that occurs:

Name and version of the database you are using: PostgreSQL 8.1

The generated SQL (show_sql=true): doesn't reach here

Debug level Hibernate log excerpt:
java.lang.ArrayIndexOutOfBoundsException: 1
at org.hibernate.event.def.DefaultFlushEntityEventListener.checkNaturalId(DefaultFlushEntityEventListener.java:79)
at org.hibernate.event.def.DefaultFlushEntityEventListener.getValues(DefaultFlushEntityEventListener.java:155)
at org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:106)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:195)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:76)

_________________
Today is yesterday's tomorrow...


Top
 Profile  
 
 Post subject: fix for natural-id ArrayIndexOutOfBounds
PostPosted: Wed Jan 25, 2006 8:26 pm 
Newbie

Joined: Sun Jan 22, 2006 7:07 pm
Posts: 2
Location: United Kingdom, Staffordshire
There does seem to be a problem when there is no second level cache enabled and the org.hibernate.persister.entity.AbstractEntityPersister creates a snapshot of naturalIdProperties and there is an element other than the natural-id fields.

I also created a new test case to make sure I am able to have n fields as natural-id properties.

Code:
int lastMarker = 0;
Object[] snapshot = new Object[ naturalIdMarkers.length ];
try {
   PreparedStatement ps = session.getBatcher().prepareSelectStatement( sql );
   try {
      getIdentifierType().nullSafeSet( ps, id, 1, session );
      ResultSet rs = ps.executeQuery();
      try {
         //if there is no resulting row, return null
         if ( !rs.next() ) {
            return null;
         }

         for ( int i = 0; i < naturalIdPropertyCount; i++ ) {
            
            /**
             *  this property must be located where the naturalIdMarker is stored
             *  the loaded natural-id loaded needs to be stored in the same position
             *  as the current object natural-id attributes
             *  and store all subsequent properties in the correct environment
             */
            for(int j = lastMarker; j < naturalIdMarkers.length; j++){
               if(naturalIdMarkers[j]==true){
                  lastMarker = j;
                  snapshot[j] = extractionTypes[i].hydrate( rs, getPropertyAliases( "", naturalIdPropertyIndexes[i] ), session, null );
                  continue;
               }
            }
         }
         return snapshot;
      }
      finally {
         rs.close();
      }
   }
   finally {
      session.getBatcher().closeStatement( ps );
   }
}

_________________
Today is yesterday's tomorrow...


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