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