nmarques
nmarques

Reputation: 151

EclipseLink TABLE_PER_CLASS inheritance: Query tries to fetch from superclass instead of concrete class

I have a model like this:

@Validated
@Entity(name = "A")
@XmlRootElement(name = "A")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlSeeAlso({B.class})
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
@UuidGenerator(name="a_key_guid")
@Cacheable(false)
public abstract class A{

}

@Entity
@Table(name = "b")
@XmlType(name = "b")
public class B extends A {

}

The A class should not have a table. Columns are omitted for simplicity.

If I try to perform a simple query, like this one:

 SELECT COUNT(*) FROM A

I get the following error, and I tried searching it but I can't find any concrete answer about this. Why isn't it fetching from the concrete class? I tried using @MappedSuperClass but the results are the same.

            Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'a' doesn't exist
    Error Code: 1146
    Call: SELECT COUNT(*) FROM A
        bind => [1 parameter bound]
    Query: ReportQuery(referenceClass=A sql="SELECT COUNT(*) FROM A")
        at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:340)
        at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:682)
        at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:558)
        at org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:1991)
        at org.eclipse.persistence.sessions.server.ClientSession.executeCall(ClientSession.java:298)
        at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:242)
        at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:228)
        at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeSelectCall(DatasourceCallQueryMechanism.java:299)
        at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.selectAllRows(DatasourceCallQueryMechanism.java:694)
        at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.selectAllRowsFromTable(ExpressionQueryMechanism.java:2738)
        at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.selectAllReportQueryRows(ExpressionQueryMechanism.java:2675)
        at org.eclipse.persistence.queries.ReportQuery.executeDatabaseQuery(ReportQuery.java:848)
        at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:899)
        at org.eclipse.persistence.queries.ObjectLevelReadQuery.execute(ObjectLevelReadQuery.java:1127)
        at org.eclipse.persistence.queries.ReadAllQuery.execute(ReadAllQuery.java:403)
        at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeInUnitOfWork(ObjectLevelReadQuery.java:1215)
        at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2896)
        at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1793)
        at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1775)
        at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1740)
        at org.eclipse.persistence.internal.jpa.QueryImpl.executeReadQuery(QueryImpl.java:258)
        ... 116 more
    Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'a' doesn't exist
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
        at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
        at com.mysql.jdbc.Util.getInstance(Util.java:386)
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1054)
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4120)
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4052)
        at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2503)
        at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2664)
        at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2815)
        at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2155)
        at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:2322)
        at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeSelect(DatabaseAccessor.java:1007)
        at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:642)
        ... 135 more

If I do create a B object and persist it, the model is updated correctly.

The version of EclipseLink is 2.5.1

Upvotes: 0

Views: 401

Answers (1)

Alan Hay
Alan Hay

Reputation: 23246

That is a native SQL query you are issuing: how is your database going to know anything about your class hierarchy or otherwise? Anyway, if A does not have a table it is not an Entity and should be a MappedSuperclass:

http://en.wikibooks.org/wiki/Java_Persistence/Inheritance#Mapped_Superclasses

Mapped superclass inheritance allows inheritance to be used in the object model, when it does not exist in the data model.

Note however that you cannot query across a class hierarchy defined by a MappedSuperclass.

Upvotes: 1

Related Questions