I have 2 java classes, one of them contains the other as a list by @ElementCollection. When I try to set that list, following error occurs:
Local Exception Stack:
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.1.3.v20110304-r9073): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLSyntaxErrorException: ORA-00942: table or view does not exist
Error Code: 942
Call: SELECT t0.VERSIONS FROM MainProcess_VERSIONS t0 WHERE (t0.MainProcess_SUBJECT_ID = ?)
bind => [#id]
Query: DirectReadQuery(name="versions" sql="SELECT t0.VERSIONS
FROM MainProcess_VERSIONS t0 WHERE (t0.MainProcess_SUBJECT_ID = ?)")
at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:333)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:683)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:526)
.
.
.
at ...Editor.MAINPROCESS._persistence_propertyChange(MAINPROCESS.java)
at ...Editor.MAINPROCESS._persistence_set_versions(MAINPROCESS.java)
at ...MAINPROCESS.setVersions(MAINPROCESS.java:79)
at ...DataModel.fillSubprocessSubject(DataModel.java:643)
at ...DataModel.load(DataModel.java:321)
If I remove the @ElementCollection
then I get the following error
Error Code: 942
Call:
SELECT t1.ACT_VERSION, t1.SUBJECT_ID, t1.ACT_VERSION_REMARK,
t1.ACT_VALID_TO, t1.ACT_VERSION_ACCEPTED, t1.NORMALRETURNVALUES, t1.ACT_VALID_FROM
FROM MAINPROCESS_MAINPROCESSVERSION t0, MAINPROCESSVERSION t1
WHERE ((t0.MainProcess_SUBJECT_ID = ?) AND ((t1.SUBJECT_ID = t0.SUBJECT_ID)
AND (t1.ACT_VERSION = t0.ACT_VERSION)))
bind => [#id]
Here are my classes,
MainProcess:
@Entity
public class MainProcess implements Serializable {
@Id
@Column(name = "SUBJECT_ID", nullable = false)
private Long subjectId;
...other columns
@ElementCollection
private List<MainProcessVersion> versions = new ArrayList<MainProcessVersion>();
public MainProcess() {
}
public void setVersions(List<MainProcessVersion> versions) {
this.versions = versions;
}
public List<MainProcessVersion> getVersions() {
return versions;
}
other getters and setters...
}
MainProcessVersion:
@Entity
@IdClass(MainProcessVersionPK.class)
public class MainProcessVersion implements Serializable {
@Id
@Column(name = "SUBJECT_ID", nullable = false)
@XmlTransient
private Long subjectId;
@Id
@Column(name = "ACT_VERSION")
private Long actVersion;
...other columns
private List<String> normalReturnValues;
public MainProcessVersion() {
}
getters and setters...
}
And the function in which the error occurs:
private MainProcess fillSubprocessSubject(Long Id) {
MainProcess p = someFacade.getProcess(Id);
List<MainProcessVersion> versions = someFacade.getProcessVersions(Id);
p.setVersions(versions); //error is here
return p;
}
Thanks in advance for any help.
I managed to solve my problem. Most important was to understand the difference between @ElementCollection
and @OneToMany
annotation. I cannot better explain like this.
So the problem was that my MainProcessVersion.java
was annotated with @Entity
, thus I could not add the @ElementCollection
annotation to it in the MainProcess.java
.
@ElementCollection //One cannot use this annotation because MainProcessVersion is an entity.
private List<MainProcessVersion> versions = new ArrayList<MainProcessVersion>();
But I need the Entity, so I created resultRow class wich is the same as my Entity class except the annotation. After query selection, I cast my result to my new resultRow class and I can set that list in the MainProcess.java
.
My resultRow class:
public class MainProcessVersionResultRow implements Serializable {
private Long subjectId;
...other code
}
My old MainProcess class
@Entity
public class MainProcess implements Serializable {
@Id
@Column(name = "SUBJECT_ID", nullable = false)
private Long subjectId;
...other columns
//without @ElementCollection and the new resultRow object type
private List<MainProcessVersionResultRow> versions = new ArrayList<MainProcessVersionResultRow>();
public MainProcess() {
}
...getters. setters
}
And then, I "cast" my entity to resultRow class:
private MainProcess fillSubprocessSubject(Long subjectId) {
MainProcess p =
someFacade.getSubprocessSubject(subjectId);
List<MainProcessVersion> versions = someFacade.getProcessVersions(subjectId);
List<MainProcessVersionResultRow> versionResultRows = new ArrayList<MainProcessVersionResultRow>();
for (MainProcessVersion vs : versions) {
MainProcessVersionResultRow versionSingleResultRow = new MainProcessVersionResultRow(vs);
versionSingleResultRow.setNormalReturnValues(processReturnValues(p.getSubjectId(), vs.getActVersion()));
versionResultRows.add(versionSingleResultRow);
}
p.setVersions(versionResultRows); //does not throw an error any more
return p;
}
So conclusion:
Do not use @ElementCollection
on a class that has an @Entity
annotation.