Search code examples
javaannotationssetter

@ElementCollection setField throws SQLSyntaxErrorException: ORA-00942


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.


Solution

  • 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.