Entity insert fails on Oracle 12c database when trying to use IDENTITY id generation strategy with hibernate.globally_quoted_identifiers=true. Entity:
@Entity
@Table(name = "COMPANY")
public class Company {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
}
hibernate.properties:
hibernate.connection.driver_class=oracle.jdbc.OracleDriver
hibernate.connection.url=...
hibernate.connection.username=...
hibernate.connection.password=...
hibernate.dialect=org.hibernate.dialect.Oracle12cDialect
hibernate.globally_quoted_identifiers=true
hibernate.show_sql=true
DDL:
create table "COMPANY" (
"id" number(10) generated by default as identity,
"name" varchar2(10),
primary key ("id")
);
Code example:
public static void main(String[] args) {
Company company = new Company();
company.setName("test");
Configuration config = new Configuration();
config.addAnnotatedClass(Company.class);
SessionFactory sessionFactory = config.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
session.save(company); transaction.commit();
session.close();
sessionFactory.close();
}
Error:
Hibernate: insert into "COMPANY" ("name") values (?)
Nov 01, 2018 6:53:34 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
WARN: SQL Error: 17068, SQLState: 99999
Nov 01, 2018 6:53:34 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
ERROR: Invalid argument(s) in call
Exception in thread "main" org.hibernate.exception.GenericJDBCException: could not prepare statement
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:47)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:113)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:182)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl.prepareStatement(StatementPreparerImpl.java:119)
at org.hibernate.dialect.identity.Oracle12cGetGeneratedKeysDelegate.prepare(Oracle12cGetGeneratedKeysDelegate.java:37)
at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:39)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3072)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3663)
at org.hibernate.action.internal.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:81)
at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:645)
at org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:282)
at org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:263)
at org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:317)
at org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:359)
at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:292)
at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:200)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:131)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:192)
at org.hibernate.event.internal.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:38)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:177)
at org.hibernate.event.internal.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:32)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:73)
at org.hibernate.internal.SessionImpl.fireSave(SessionImpl.java:709)
at org.hibernate.internal.SessionImpl.save(SessionImpl.java:701)
at org.hibernate.internal.SessionImpl.save(SessionImpl.java:696)
at Example.main(Example.java:24)
Caused by: java.sql.SQLException: Invalid argument(s) in call
at oracle.jdbc.driver.AutoKeyInfo.getNewSql(AutoKeyInfo.java:187)
at oracle.jdbc.driver.PhysicalConnection.prepareStatement(PhysicalConnection.java:4342)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$3.doPrepare(StatementPreparerImpl.java:117)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:172)
... 23 more
The same works fine if I set
hibernate.globally_quoted_identifiers=false
and change DDL correspondingly to:
create table COMPANY (
id number(10) generated by default as identity,
name varchar2(10),
primary key (id)
);
When debugging the error I noticed that oracle.jdbc.driver.AutoKeyInfo#getReturnParamTypeCode tries to find "id" (with quotes) in an array of columns without quotes oracle.jdbc.driver.AutoKeyInfo#tableColumnNames. The array must be retrieved directly from database by the driver itself (to prove that I added a new column Hibernate is not aware about and that column was included into the array) and the quoted column must be coming from Hibernate. Note that with the same driver version and DDL (with and without quotes) I am able to run native queries via java.sql.Connection#prepareStatement. Also when I tried lowercase table name @Table(name = "company") with global quoting option and corresponding changes in DDL have been made I got another error:
Hibernate: insert into "company" ("name") values (?)
...
Exception in thread "main" org.hibernate.exception.SQLGrammarException: could not prepare statement
at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:63)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:113)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:182)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl.prepareStatement(StatementPreparerImpl.java:119)
at org.hibernate.dialect.identity.Oracle12cGetGeneratedKeysDelegate.prepare(Oracle12cGetGeneratedKeysDelegate.java:37)
at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:39)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3072)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3663)
at org.hibernate.action.internal.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:81)
at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:645)
at org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:282)
at org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:263)
at org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:317)
at org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:359)
at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:292)
at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:200)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:131)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:192)
at org.hibernate.event.internal.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:38)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:177)
at org.hibernate.event.internal.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:32)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:73)
at org.hibernate.internal.SessionImpl.fireSave(SessionImpl.java:709)
at org.hibernate.internal.SessionImpl.save(SessionImpl.java:701)
at org.hibernate.internal.SessionImpl.save(SessionImpl.java:696)
at Example.main(Example.java:24)
Caused by: java.sql.SQLSyntaxErrorException: ORA-04043: object "COMPANY" does not exist
at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:494)
at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:441)
at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:436)
at oracle.jdbc.driver.T4CTTIfun.processError(T4CTTIfun.java:1061)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:623)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:252)
at oracle.jdbc.driver.T4C8Odsy.doODSY(T4C8Odsy.java:137)
at oracle.jdbc.driver.T4C8Odsy.doODSYTable(T4C8Odsy.java:119)
at oracle.jdbc.driver.T4CConnection.doDescribeTable(T4CConnection.java:4605)
at oracle.jdbc.driver.PhysicalConnection.prepareStatement(PhysicalConnection.java:4340)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$3.doPrepare(StatementPreparerImpl.java:117)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:172)
... 23 more
Even though the errors seem to be different they might have something in common. |