We're updating the issue view to help you get more done. 

SQLGrammarException with @DiscriminatorColumn in an inheritance hierarchy

Description

I recently stumbled upon a possible bug with the discriminator column in an inheritance hierarchy.

You can find the appropiate test case here: https://github.com/shiruba/hibernate-discriminatorvalue-test

Suppose I got the following inheritance hierarchy:

1 2 3 4 @Entity @Inheritance(strategy = InheritanceType.JOINED) @DiscriminatorColumn public class Parent {}
1 2 @Entity public class SpecialParent extends Parent {}
1 2 @Entity public class VerySpecialParent extends SpecialParent {}

If I try to persist an instance of SpecialParent, I get the following stacktrace:

INFO: HHH000327: Error performing load command : org.hibernate.exception.SQLGrammarException: could not extract ResultSet

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not extract ResultSet at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1763) at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1677) at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1683) at org.hibernate.jpa.spi.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:1206) at de.codecentric.hibernate.DiscriminatorColumnTest.testDiscriminatorValueInInheritanceWithConcreteType(DiscriminatorColumnTest.java:22) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) at org.junit.runners.ParentRunner.run(ParentRunner.java:309) at org.junit.runner.JUnitCore.run(JUnitCore.java:160) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:74) at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:211) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:67) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134) Caused by: org.hibernate.exception.SQLGrammarException: could not extract ResultSet at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:80) at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49) at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:126) at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:112) at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:91) at org.hibernate.loader.Loader.getResultSet(Loader.java:2065) at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1862) at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1838) at org.hibernate.loader.Loader.doQuery(Loader.java:909) at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:354) at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:324) at org.hibernate.loader.Loader.loadEntity(Loader.java:2148) at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:78) at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:68) at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:4126) at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:503) at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:468) at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:213) at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:275) at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:151) at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1070) at org.hibernate.internal.SessionImpl.access$2000(SessionImpl.java:176) at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.load(SessionImpl.java:2551) at org.hibernate.internal.SessionImpl.get(SessionImpl.java:960) at org.hibernate.event.internal.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:306) at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:186) at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:85) at org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:876) at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:858) at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:863) at org.hibernate.jpa.spi.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:1196) ... 27 more Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'specialpar0_.DTYPE' in 'field list' at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:408) at com.mysql.jdbc.Util.handleNewInstance(Util.java:408) at com.mysql.jdbc.Util.getInstance(Util.java:383) at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1062) at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4226) at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4158) at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2615) at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2776) at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2840) at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2082) at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:2212) at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:82) ... 53 more

If I remove the @DiscriminatorColumn annotation at Parent, everything works fine. This led me to reading the spec and paragraph 11.1.12, which I understand as follows:

  • The @DiscriminatorColumn annotation is optional for the SINGLE_TABLE and JOINED inheritance strategies.

  • In case no @DiscriminatorColumn is specified, the discriminator column name defaults to DTYPE and the type to STRING.

  • A @DiscriminatorColumn has to be specified at the root of the inheritance hierarchy.

  • A @DiscriminatorColumn can be used in a subhierarchy in which a different inheritance strategy shall be applied.

  • A @DiscriminatorValue will be generated, if none was provided.

Obviously, Hibernate expects the discriminator column to be somewhere else, but not on the direct super class.

This leads to my question: Is this a bug OR is this a configuration issue (in which case Hibernate should not generate invalid SQL but throw an exception of some kind)?

Environment

Hibernate Core/EntityManager 4.3.6.Final
Java 1.7

Status

Assignee

Andrea Boriero

Reporter

Sascha Fröhlich

Fix versions

Labels

backPortable

None

Suitable for new contributors

None

Requires Release Note

None

Pull Request

None

backportDecision

None

Components

Affects versions

4.3.6
4.3.1
5.0.0.Final
4.3.4
4.3.5
4.3.3
5.0.3
4.3.2
5.0.2
5.0.1

Priority

Major