Hello All,
I am having a strange issue with a Hibernate collection and difficulty debugging it. I work in a multi-developer team and my unit tests appear to have suddenly started breaking. I have a mapping that was working perfectly until now, now I am getting a strange error whenever I try to save a collection. I have an outer object that contains a collection of inner objects. The inner objects save just fine in isolation. The outer object saves just fine if it has no inner classes (it’s member variable of collection List is null). The outer object also works perfectly if the list has a count of one. When I add 2 or more objects to the list, I get the error below. To make the issue even stranger, I’m using the identical @OneToMany syntax in many other instances without issue (the mapping patterns is repeated about a half-dozen times throughout my application.
Any help troubleshooting this issue is greatly appreciated.
Steven
Here's the error:
Code:
Hibernate: insert into response_structure_metadata (default_points, input_palettes_id, rsmd_identifier, cc_id, maple_graph, rsmd_type_id, rsmd_id) values (?, ?, ?, ?, ?, ?, ?)
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
at oracle.jdbc.driver.T4CTTIrxd.marshal(T4CTTIrxd.java:230)
at oracle.jdbc.driver.T4C8Oall.marshalBinds(T4C8Oall.java:1496)
at oracle.jdbc.driver.T4C8Oall.marshalAll(T4C8Oall.java:973)
at oracle.jdbc.driver.T4C8Oall.marshal(T4C8Oall.java:422)
Hibernate: insert into feedback_conditions (conditional_script, general_feedback_text, individual_feedback_text, fbc_id) values (?, ?, ?, ?)
Hibernate: insert into feedback_conditions (conditional_script, general_feedback_text, individual_feedback_text, fbc_id) values (?, ?, ?, ?)
2006-05-16 13:24:55,343 ERROR [org.hibernate.jdbc.AbstractBatcher] - <Exception executing batch: >
java.lang.ArrayIndexOutOfBoundsException: 3
at oracle.jdbc.driver.T4CTTIrxd.marshal(T4CTTIrxd.java:230)
at oracle.jdbc.driver.T4C8Oall.marshalBinds(T4C8Oall.java:1496)
at oracle.jdbc.driver.T4C8Oall.marshalAll(T4C8Oall.java:973)
at oracle.jdbc.driver.T4C8Oall.marshal(T4C8Oall.java:422)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:202)
at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:955)
at oracle.jdbc.driver.OraclePreparedStatement.executeBatch(OraclePreparedStatement.java:10581)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:58)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:195)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:230)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:140)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:296)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1009)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:356)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
at foo.data.dao.UniversalDAO.saveObj(UniversalDAO.java:30)
at foo.data.dao.UnitTestsDAO.saveRSMD(UnitTestsDAO.java:120)
at foo.data.persistence.tests.TestRSMD.testRSMD(TestRSMD.java:70)
at foo.data.persistence.tests.TestRSMD.main(TestRSMD.java:22)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:202)
at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:955)
at oracle.jdbc.driver.OraclePreparedStatement.executeBatch(OraclePreparedStatement.java:10581)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:58)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:195)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:230)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:140)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:296)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1009)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:356)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
at foo.data.dao.UniversalDAO.saveObj(UniversalDAO.java:30)
at foo.data.dao.UnitTestsDAO.saveRSMD(UnitTestsDAO.java:120)
at foo.data.persistence.tests.TestRSMD.testRSMD(TestRSMD.java:70)
at foo.data.persistence.tests.TestRSMD.main(TestRSMD.java:22)
Here's the outer classCode:
package foo.data.persistence;
import java.util.List;
import javax.persistence.*;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.IndexColumn;
import foo.model.ResponseStructureMetaData;
@Entity
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@SequenceGenerator(name="seq0", sequenceName="rsmd_seq")
@Table(name="response_structure_metadata")
public class ResponseStructureMetaDataTO implements ResponseStructureMetaData {
private int id;
private boolean mapleGraph;
private InputPaletteTO inputPalette;
private int defaultPoints;
private String rsmdIdentifier;
private CorrectnessConditionTO correctnessCondition;
private List<FeedbackConditionTO> feedbackConditions;
private RSMDTypeTO type;
public ResponseStructureMetaDataTO(){}
public ResponseStructureMetaDataTO(String rsmdIdentifier, boolean mapleGraph, InputPaletteTO inputPalette, int numberOfPoints, RSMDTypeTO type){
setRsmdIdentifier(rsmdIdentifier);
setMapleGraph(mapleGraph);
setInputPalette(inputPalette);
setDefaultPoints(numberOfPoints);
setType(type);
}
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="seq0")
@Column(name="rsmd_id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name="input_palettes_id")
public InputPaletteTO getInputPalette() {
return inputPalette;
}
public void setInputPalette(InputPaletteTO inputPalette) {
this.inputPalette = inputPalette;
}
@Column(name="default_points")
public int getDefaultPoints() {
return defaultPoints;
}
public void setDefaultPoints(int numberOfPoints) {
this.defaultPoints = numberOfPoints;
}
@Column(name="rsmd_identifier")
public String getRsmdIdentifier() {
return rsmdIdentifier;
}
public void setRsmdIdentifier(String rsmdIdentifier) {
this.rsmdIdentifier = rsmdIdentifier;
}
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name="cc_id")
public CorrectnessConditionTO getCorrectnessCondition() {
return correctnessCondition;
}
public void setCorrectnessCondition(CorrectnessConditionTO correctnessCondition) {
this.correctnessCondition = correctnessCondition;
}
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
@JoinTable(
name="rsmd_feedback",
joinColumns=@JoinColumn(name="rsmd_id"),
inverseJoinColumns=@JoinColumn(name="fbc_id")
)
@IndexColumn(name = "evaluation_order", base=1)
public List<FeedbackConditionTO> getFeedbackConditions() {
return feedbackConditions;
}
public void setFeedbackConditions(List<FeedbackConditionTO> feedbackConditions) {
this.feedbackConditions = feedbackConditions;
}
@Column(name="maple_graph")
public boolean isMapleGraph() {
return mapleGraph;
}
public void setMapleGraph(boolean mapleGraph) {
this.mapleGraph = mapleGraph;
}
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name="rsmd_type_id")
public RSMDTypeTO getType() {
return type;
}
public void setType(RSMDTypeTO type) {
this.type = type;
}
}
Here's the inner class:Code:
package foo.data.persistence;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
@Entity
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@SequenceGenerator(name="seq0", sequenceName="feedback_cond_seq")
@Table(name="feedback_conditions")
public class FeedbackConditionTO {
private int id;
private String conditional;
private String generalFeedbackText;
private String individualFeedbackText;
public FeedbackConditionTO(){}
public FeedbackConditionTO(String condition, String generalFeedbackText, String individualFeedbackText){
setConditional(condition);
setGeneralFeedbackText(generalFeedbackText);
setIndividualFeedbackText(individualFeedbackText);
}
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="seq0")
@Column(name="fbc_id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(name="conditional_script")
public String getConditional() {
return conditional;
}
public void setConditional(String conditional) {
this.conditional = conditional;
}
@Column(name="general_feedback_text")
public String getGeneralFeedbackText() {
return generalFeedbackText;
}
public void setGeneralFeedbackText(String generalFeedbackText) {
this.generalFeedbackText = generalFeedbackText;
}
@Column(name="individual_feedback_text")
public String getIndividualFeedbackText() {
return individualFeedbackText;
}
public void setIndividualFeedbackText(String individualFeedbackText) {
this.individualFeedbackText = individualFeedbackText;
}
/**
* This method is used for developer debugging.
* If it's ever used in production, please update comments.
*/
public String toString(){
return "FeedbackConditionTO("+ id + ", script = '" + conditional + "', general = '" +
generalFeedbackText + "' individual='" + individualFeedbackText + "')";
}
}
[/b]