-->
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: Error when saving an indexed collection
PostPosted: Wed Sep 23, 2009 5:51 am 
Newbie

Joined: Fri Aug 14, 2009 8:06 am
Posts: 19
Hi,

I am experiencing trouble with persisting a List in a class that has children that are instances of the same class. Everything works fine until I commit everything. Then, when calling the getIndex() method, it returns -1, leading to an ArrayIndexOutOfBounds exception. I debugged the code and when committing, for some reason, the child collection of the parent is empty, although this was not the case when saving.

Configuration file:

Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="be.bloso.vetrasoft.model.application">
   <class name="DataItem" table="DATAITEM">
      <id name="id" column="DATAITEM_ID">
         <generator class="hilo" />
      </id>

      <property name="rootData" />
      <property name="data"  />
      <property name="deprecated"  />
      <property name="index"  />

      <many-to-one name="parent" class="DataItem" />

      <list name="allSubData" inverse="true" lazy="true" table="DATAITEM">
         <key column="DATAITEM_ID" />
         <list-index column="INDEX" />
         <one-to-many class="DataItem" />
      </list>
   </class>
</hibernate-mapping>


Source code of the class:

Quote:
/*
* Created on Nov 17, 2008
*/

package be.bloso.vetrasoft.model.application;

import java.io.Serializable;
import java.util.List;

import be.bloso.vetrasoft.model.ListenerHandler;
import be.bloso.vetrasoft.util.HibernateUtil;
import be.bloso.vetrasoft.util.UniqueList;

/**
* TODO Comment class
*
* @author Stef Kuypers - Impro Dynamics
*/
public class DataItem implements Comparable<DataItem>, Serializable, DataChangeListener {
private static final long serialVersionUID = 1L;

private Long id;
private Data rootData;
private DataItem parent;
private String data;
private final UniqueList<DataItem> subData = new UniqueList<DataItem>();
private boolean deprecated = false;

protected DataItem() {
super(); // Used by Hibernate
}

DataItem(Data rootData, String data, boolean standard) {
if (data == null) {
throw new IllegalArgumentException("The data can not be null");
}

this.rootData = rootData;
this.data = data;
parent = null;
}

DataItem(Data rootData, String data) {
this(rootData, data, false);
}

DataItem(DataItem parent, String data) {
this(parent.getRootData(), data);

this.parent = parent;
}

public Long getId() {
return id;
}

protected void setIndex(int index) {
// Not used. Necessary for Hibernate.
}

public int getIndex() {
return parent == null ? rootData.indexOf(this) : parent.getAllSubData().indexOf(this);
}

protected void setId(Long id) {
this.id = id;
}

public Data getRootData() {
return rootData;
}

protected void setRootData(Data rootData) {
this.rootData = rootData;
}

public void setDeprecated(boolean deprecated) {
this.deprecated = deprecated;

for (DataItem item : subData) {
item.setDeprecated(deprecated);
}
}

public boolean isDeprecated() {
return deprecated;
}

public DataItem getParent() {
return parent;
}

protected void setParent(DataItem parent) {
this.parent = parent;
}

public int getLevel() {
return level;
}

protected void setLevel(int level) {
this.level = level;
}

public String getData() {
return data;
}

public void setData(String string) {
this.data = string;
}

@Override
public String toString() {
return data;
}

public List<DataItem> getAllSubData() {
return subData;
}

protected void setAllSubData(List<DataItem> subData) {
this.subData.clear();
this.subData.addAll(subData);
}

public DataItem getSubData(String string) {
DataItem item = null;
int index = 0;

while (index < subData.size() && item == null) {
DataItem subItem = subData.get(index);

if (subItem.toString().equals(string)) {
item = subItem;
}

index++;
}

return item;
}

public DataItem addSubData(String string) {
DataItem item = getSubData(string);

if (item == null) {
item = new DataItem(this, string);
subData.add(item);
}

return item;
}

public int compareTo(DataItem item) {
if (item.rootData != rootData) {
throw new IllegalArgumentException("Can not compare data items from different data sets.");
}

return toString().compareTo(item.toString());
}

@Override
public int hashCode() {
return super.hashCode() + 37 * data.hashCode() + 37 * 37 * rootData.hashCode();
}
}


Data is an enumeration, UniqueList is a wrapper for ArrayList that also implements the Set interface.

The code I execute is the following:

Code:
      DataItem dataItem = Data.ACCENT.add("test");
      DataItem subData1;
      DataItem subData2;

      session.beginTransaction();
      session.save(dataItem);

      subData1 = dataItem.addSubData("subdata 1");
      subData2 = dataItem.addSubData("subdata 2");

      session.save(subData1);
      session.save(subData2);
      session.getTransaction().commit(); // <-- This is where getIndex() returns -1


I'm sure it must be something simple but googling the problem has not solved it.

Cheers,
Stef


Top
 Profile  
 
 Post subject: Re: Error when saving an indexed collection
PostPosted: Wed Sep 23, 2009 6:06 am 
Newbie

Joined: Fri Aug 14, 2009 8:06 am
Posts: 19
Apparently this has to do with the fact that I clear the collection in the setAllSubData() method. Is this normal behavior?

Anyway, I commented out that line of code now but when I load the data again things really start to go wrong. The DataItem I created first now has itself as subdata, so does the second and the third now has null and itself as subdata. There a 4th I added and this one too has null and itself as subdata.

Here's the updated test code:

Code:
DataItem dataItem = Data.ACCENT.add("test");
      DataItem subData1;
      DataItem subData2;

      session.beginTransaction();
      session.save(dataItem);

      subData1 = dataItem.addSubData("subdata 1");
      subData2 = dataItem.addSubData("subdata 2");

      session.save(subData1);
      session.save(subData2);
      session.getTransaction().commit();

      DataItem subData3 = dataItem.addSubData("subdata 3");

      session = HibernateUtil.getSessionFactory().getCurrentSession();

      session.beginTransaction();
      session.save(subData3);
      session.getTransaction().commit();

      HibernateUtil.closeSessionFactory(); // closes down the database
      session = HibernateUtil.getSessionFactory().getCurrentSession();

      session.beginTransaction();

      List<DataItem> results = session.createQuery("from DataItem").list();

      Assert.assertEquals(4, results.size());

      dataItem = results.get(0);
      Assert.assertSame(Data.ACCENT, dataItem.getRootData());
      Assert.assertEquals("test", dataItem.getData());
      Assert.assertEquals(3, dataItem.getAllSubData().size()); <- Upon inspection I came to the conclusions stipulated above


Cheers,
Stef


Top
 Profile  
 
 Post subject: Re: Error when saving an indexed collection
PostPosted: Thu Sep 24, 2009 3:48 am 
Newbie

Joined: Fri Aug 14, 2009 8:06 am
Posts: 19
Ok, I found the problem. It was an error in the mapping file.

For those that should encounter the same problem, the correct mapping is this:

Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="be.bloso.vetrasoft.model.application">
   <class name="DataItem" table="DATAITEM">
      <id name="id" column="DATAITEM_ID">
         <generator class="hilo" />
      </id>

      <property name="rootData" />
      <property name="data"  />
      <property name="deprecated"  />
      <property name="index"  />

      <many-to-one name="parent" class="DataItem" />

      <list name="allSubData" inverse="true" lazy="true" table="DATAITEM">
         <key column="parent" /> <!-- COLUMN IS parent INSTEAD OF dataitem_id -->
         <list-index column="INDEX" />
         <one-to-many class="DataItem" />
      </list>
   </class>
</hibernate-mapping>


Cheers,
Stef


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.