3

问题:错误 500:内部服务器错误

URI: /listing/save
Class: org.hibernate.AssertionFailure
Message: getGeneratedKeys() support is not enabled

配置

  • 环境:发展
  • 应用简介:网络
  • 应用版本:0.1
  • Grails 版本:3.0.1
  • Groovy 版本:2.4.3
  • JVM 版本:1.8.0_45(64 位)
  • 重新加载活动:true

可用控制器:

  • 电话簿.ListingController

操作系统:Windows 7 数据库:Oracle 11g R2 企业版(11.2.0.4 64 位)

调试输出包含:

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

重现问题:

  • C:\Dev> grails 创建应用电话簿
  • C:\Dev> cd 电话簿

编辑:build.gradle

dependencies {
  ...
  runtime "com.oracle:jdbc-lib-ojdbc6:11.2.0.4"
  ...
}

注意:Oracle 客户端 ojdbc6.jar 在上面指定的坐标处添加到本地 Maven 存储库。

编辑: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 编辑: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

下面确认应用程序连接数据库并成功创建表:

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)

架构中还创建了两个序列:

HIBERNATE_SEQUENCE
LISTING_SEQ

注意:这些肯定是由于我多次尝试修改域类中的映射属性以生成 ID 的结果而创建的。

嵌入式 Tomcat 服务器在http://localhost:8080/上运行后的操作 Internet Explorer:http://localhost:8080/ 单击链接:可用控制器 > phonebook.ListingController 单击:新建列表完成表单并单击:创建结果:上述 Grails 异常

研究和故障排除活动:

  • 不存在的问题只是 Oracle 到 H2/HSQL 文件/内存数据库的变化
  • 发现 hibernate.jdbc.use_get_generated_keys 设置,但通过在 application.yml 配置文件中设置 true 未能成功解决问题
  • 在 grails-app/conf/DataSource.groovy 中找到了对设置的多个引用,但这是使用 application.yml 的 Grails 3
  • 尝试在域类中使用生成器映射 ID 列的多个属性
  • 在涵盖此主题的 Grails 3 文档中几乎没有发现任何信息
  • Hibernate 文档涵盖了配置设置和 ID 生成器,但不提供该信息的 Grails / Groovy 应用程序
  • Hibernate 文档指出,不显式设置 hibernate.jdbc.use_get_generated_keys 会导致它由 jdbc 连接数据库元数据自动设置

我试图通过 grails-app\conf\application.yml 中的以下部分来解决问题:

hibernate:
    jdbc:
        use_get_generated_keys: true
    cache:
        queries: false
...

我怀疑该解决方案涉及 grails-app\conf\application.yml 中的特定设置,但尚未发现配置设置的正确组合。

4

4 回答 4

1

好的,当查看 application.yml 配置文件中放置第一个答案中的建议的位置时,我发现我使用的 hibernate.jdbc.use_get_generated_keys = true 设置实际上位于 grails 块下。虽然以前从未使用过 yml 文件,但我没有意识到缩进和块如何形成配置设置的潜在重要性。当我第一次对文件进行编辑时,我查看是否已经有一个休眠部分,我将此设置放在该块中,从而产生 grails.hibernate.jdbc.use_get_generated_keys 的设置。我在根目录下创建了设置(无缩进)以进行休眠并进行了测试。结果是成功完成了动作。

我希望这篇文章能帮助其他新用户使用这个在以 groovy 为中心的框架中看起来不合适的配置文件。我将看看是否有一个选项可以创建一个新的 grails 应用程序来使用 groovy 配置文件而不是 yml 文件。

于 2015-06-10T03:56:09.327 回答
0

您还可以尝试从身份序列生成器(我相信 Oracle 方言的默认设置)切换到 seq-hilo:

在 Grails 2.x 中,您可以通过以下方式进行:

grails.gorm.default.mapping = {
    id generator: 'seqhilo', params: [max_lo: 1000]
}

我认为它在 application.yml 文件中的 3.x 中会类似地工作。这应该可以防止休眠甚至需要使用 getGeneratedKeys() 方法,因为它会将 id 从它自己的内存池中绑定到插入中,而不是在插入语句中执行 seq.nextval。

于 2015-06-09T22:09:53.987 回答
0

对于 Grails 3、Hibernte 4、Oracle 10c+,以下配置有效。

在 build.gradle 中配置 Hibernate 4,默认情况下从 Grails 3.1.6 开始

在 application.yml

hibernate:
    jdbc:
        use_get_generated_keys: true
    id:
        new_generator_mappings: true

然后在域对象中配置 id 字段以使用 Oracle 序列作为键,如下所示:

class Person {

    String name

    static constraints = {
        id generator:'sequence-identity', params:[sequence:'person_key_seq']
    }
}

Oracle 最近才推出了自动生成的 ID 字段,我想是 12。但是 Hibernate 4 只有 org.hibernate.dialect.Oracle10gDialect,所以没有 Hibernate 5 就不能使用新的 Oracle 自动键功能。如果可以使用Hibernate 5 然后 Oracle12cDialect 可用,这将允许 Hibernate 和 Oracle 在直接处理数据库时在 GORM 和 SQL 中为您处理密钥生成。但是,从 Grails 3.1.6 开始,在某些服务器上成功部署 Hibernate 5 存在问题,因此如果您尝试切换,请小心。

于 2016-05-06T18:54:43.070 回答
0

Oracle 12 有这个问题,通过添加修复

   jdbc:
      use_get_generated_keys: true

并将 oracle jdbc 驱动程序升级到 ojdbc7 12.1.0.2(12.1.0.1 不起作用)

于 2016-01-26T18:16:55.867 回答