Problem: Error 500: Internal Server Error
URI: /listing/save
Class: org.hibernate.AssertionFailure
Message: getGeneratedKeys() support is not enabled
Configuration
- Environment: development
- App profile: web
- App version: 0.1
- Grails version: 3.0.1
- Groovy version: 2.4.3
- JVM version: 1.8.0_45 (64-bit)
- Reloading active: true
Available Controllers:
- phonebook.ListingController
Operating System: Windows 7 Database: Oracle 11g R2 Enterprise Edition (11.2.0.4 64-bit)
Debug output contains:
Grails application running at http://localhost:8080
ERROR org.hibernate.AssertionFailure - HHH000099: an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session): org.hibernate.AssertionFailure: getGeneratedKeys() support is not enabled
ERROR org.grails.web.errors.GrailsExceptionResolver - AssertionFailure occurred when processing request: [POST] /listing/save - parameters:
name: Scott
phone: 555-1212
create: Create
getGeneratedKeys() support is not enabled. Stacktrace follows:
org.hibernate.AssertionFailure: getGeneratedKeys() support is not enabled
at phonebook.ListingController.$tt__save(ListingController.groovy:38) ~[main/:na]
at grails.transaction.GrailsTransactionTemplate$2.doInTransaction(GrailsTransactionTemplate.groovy:93) ~[grails-core-3.0.1.jar:3.0.1]
at grails.transaction.GrailsTransactionTemplate.execute(GrailsTransactionTemplate.groovy:90) ~[grails-core-3.0.1.jar:3.0.1]
at grails.transaction.GrailsTransactionTemplate$2.doInTransaction(GrailsTransactionTemplate.groovy:93) ~[grails-core-3.0.1.jar:3.0.1]
at grails.transaction.GrailsTransactionTemplate.execute(GrailsTransactionTemplate.groovy:90) ~[grails-core-3.0.1.jar:3.0.1]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) ~[na:1.8.0_45]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) ~[na:1.8.0_45]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_45]
File: grails-app\controllers\phonebook\ListingController
Line: 38
Content: listing.save flush:true
Reproducing problem:
- C:\Dev> grails create-app phonebook
- C:\Dev> cd phonebook
Edit: build.gradle
dependencies {
...
runtime "com.oracle:jdbc-lib-ojdbc6:11.2.0.4"
...
}
Note: Oracle client ojdbc6.jar added to local Maven repository at the coordinates specified above.
Edit: grails-app\conf\application.yml
...
dataSource:
pooled: true
jmxExport: true
driverClassName: oracle.jdbc.OracleDriver
username: scott
password: tiger
environments:
development:
dataSource:
dbCreate: update
url: jdbc:oracle:thin:@localhost:1521/sbx1
...
C:\Dev\phonebook> grails create-domain-class phonebook.listing Edit:grails-app\domain\phonebook\Listing.groovy
package phonebook
class Listing {
String name
String phone
static constraints = {
name maxSize: 50
phone maxSize: 14
}
}
C:\Dev\phonebook> grails generate-all phonebook.listing
C:\Dev\phonebook> grails run-app
The following confirms that the application connected to the database and created the table successfully:
SQL> describe listing
Name Null? Type
----------------------------------------- -------- ----------------------------
ID NOT NULL NUMBER(19)
VERSION NOT NULL NUMBER(19)
NAME NOT NULL VARCHAR2(50 CHAR)
PHONE NOT NULL VARCHAR2(14 CHAR)
There are also two sequences created in the schema:
HIBERNATE_SEQUENCE
LISTING_SEQ
Note: These must have been created as a result at my many attempts to modify mapping attributes in the domain class for ID generation.
Action once embedded Tomcat server is running on http://localhost:8080/ Internet Explorer: http://localhost:8080/ Click on link: Available Controllers > phonebook.ListingController Click on: New Listing Complete form and click: Create Result: Grails exception described above
Research and troubleshooting activities:
- Problem not present is only change is Oracle to H2/HSQL file/memory database
- Discovered hibernate.jdbc.use_get_generated_keys setting but was unsuccessful in resolving issue by placing setting of true in application.yml configuration file
- Found multiple references to settings in grails-app/conf/DataSource.groovy but this is Grails 3 which uses application.yml
- Attempted multiple attributes in domain class for mapping ID column using generators
- Found little to no information in Grails 3 documentation covering this topic
- Hibernate documentation covers configuration settings and ID generators but does not provide Grails / Groovy application of that information
- Hibernate documentation states that not explicitly setting hibernate.jdbc.use_get_generated_keys results in it being set automatically by jdbc connection database metadata
I attempted to resolve the problem by the following section in grails-app\conf\application.yml:
hibernate:
jdbc:
use_get_generated_keys: true
cache:
queries: false
...
I suspect that the resolution involves specific settings in grails-app\conf\application.yml but have not discovered the correct combination of configuration settings.
You could also try switching from the identity-sequence generator (the default for Oracle dialect, I believe), to the seq-hilo:
In Grails 2.x, you do it via:
I assume it would work similarly in 3.x in the application.yml file. This should prevent hibernate from even needing to use the getGeneratedKeys() method as it will bind the id into the insert from it's own in-memory pool instead of doing a seq.nextval in the insert statement.