HQL to access the subclass object of @manytoOne fields

931 views Asked by At

I have scenario in which below is the superclass:-

abstract class  Container
{
    Long id;
    FieldParent parent;
}

class SubContainer extends Container
{
    Long extid;
}

abstract class FieldParent
{
    Long fid;
    String name;
}

class SubField  extends FieldParent
{
    String typeOfSub;
}

I am using Table per subclass strategy using a discriminator Below is hbm mapping of Container:-

<class name="Container" table="Container">
    <id name="id" type="long" column="ID">
        <generator class="native"/>
    </id>
     <many-to-one name="parent"
                     class="FieldParent"
                     cascade="none"
                     column="FieldParentID"/>
    <discriminator column="TYPE"/>
    ....
    <subclass name="SubContainer"
                  discriminator-value="S"
                  lazy="true">
          <property name="extid"  type="long"  column="extid" not-null="true"/>
    </subclass>
</class>

Below is hbm mapping of FieldParent:-

   <class name="FieldParent" table="FieldParent">
        <id name="fid" type="long" column="FID">
            <generator class="native"/>
        </id>
        <property name="name"  type="java.lang.String"  column="name" not-null="true"/>
        <discriminator column="TYPE_Parent"/>
        ....
        <subclass name="SubField"
                      discriminator-value="F"
                      lazy="true">
            <property name="typeOfSub"  type="java.lang.String"  column="typeOfSub" not-null="true"/>
        </subclass>
    </class>

Now I have the object of SubContainer and I am query based on 'typeOfSub' value. I tried using below query

getHibernateTemplate().find(
        "from " + SubContainer.class.getName()
                + " subContainer where subContainer.extid = ? and subContainer.parent.typeOfSub=? ",
        new Object[]{new Long(id), "sampeTypeoFSub"});

but faced 'org.hibernate.PropertyAccessException: IllegalArgumentException occurred '.
I understand I cant be just assume that it will be SubField object so cant access the fields but I need to figuure out the way for. I am not sure if we can cast in HQL?
I tried searching for the resolution but dint find any similar question.

Below is the stacktrace :

java.sql.SQLSyntaxErrorException: ORA-00904: "FieldParent_3_"."typeOfSub": invalid identifier at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:445) [ojdbc6.jar:11.2.0.3.0] at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:396) [ojdbc6.jar:11.2.0.3.0] at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:879) [ojdbc6.jar:11.2.0.3.0] at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:450) [ojdbc6.jar:11.2.0.3.0] at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:192) [ojdbc6.jar:11.2.0.3.0] at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:531) [ojdbc6.jar:11.2.0.3.0] at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:207) [ojdbc6.jar:11.2.0.3.0] at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:884) [ojdbc6.jar:11.2.0.3.0] at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:1167) [ojdbc6.jar:11.2.0.3.0] at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1281) [ojdbc6.jar:11.2.0.3.0] at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3584) [ojdbc6.jar:11.2.0.3.0] at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3628) [ojdbc6.jar:11.2.0.3.0] at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeQuery(OraclePreparedStatementWrapper.java:1493) [ojdbc6.jar:11.2.0.3.0] at org.jboss.resource.adapter.jdbc.WrappedPreparedStatement.executeQuery(WrappedPreparedStatement.java:342) [:6.0.0.Final]

Updated stack trace for exception.Also just FYI, FieldParent has 3 subclasses one of which is SubField .

java.sql.SQLSyntaxErrorException: ORA-00904: "FieldParent1_3_"."typeOfSub": invalid identifier

    at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:445) [ojdbc6.jar:11.2.0.3.0]
    at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:396) [ojdbc6.jar:11.2.0.3.0]
    at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:879) [ojdbc6.jar:11.2.0.3.0]
    at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:450) [ojdbc6.jar:11.2.0.3.0]
    at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:192) [ojdbc6.jar:11.2.0.3.0]
    at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:531) [ojdbc6.jar:11.2.0.3.0]
    at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:207) [ojdbc6.jar:11.2.0.3.0]
    at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:884) [ojdbc6.jar:11.2.0.3.0]
    at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:1167) [ojdbc6.jar:11.2.0.3.0]
    at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1281) [ojdbc6.jar:11.2.0.3.0]
    at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3584) [ojdbc6.jar:11.2.0.3.0]
    at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3628) [ojdbc6.jar:11.2.0.3.0]
    at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeQuery(OraclePreparedStatementWrapper.java:1493) [ojdbc6.jar:11.2.0.3.0]
    at org.jboss.resource.adapter.jdbc.WrappedPreparedStatement.executeQuery(WrappedPreparedStatement.java:342) [:6.0.0.Final]
    at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:208) [:3.6.10.Final]
    at org.hibernate.loader.Loader.getResultSet(Loader.java:1953) [:3.6.10.Final]
2

There are 2 answers

2
Vlad Mihalcea On

The typeOfSub property is in the SubField class and the Container has a many-to-one association to a FieldParent instead.

  1. You either move the property into FieldParent
  2. You filter the association to the subclass type:

    select subContainer
    from SubContainer subContainer
    where 
        subContainer.parent.class = my.package.SubField
        subContainer.extid = ? and 
        subContainer.parent.typeOfSub=?
    
0
Viraj Nalawade On

I tried @VladMihalcea answers but sadly dint work. After digging more into the issue I dont think its possible to do access subclasses elements in HQL. So here's what I did as workaround and worked for me.

getHibernateTemplate().find("select subCont from " +SubContainer.class.getName()+" subCont, " + SubField.class.getName() +" subField "
where subCont.extid = ? and subField.typeOfSub=? and subCont.parent.fid=subField.fid",
        new Object[]{new Long(id), "sampeTypeoFSub"});

Basically joing the tables. Kind of similar to inner join.