【问题标题】:Grails reverse engineering and table/column naming strategyGrails 逆向工程和表/列命名策略
【发布时间】:2014-09-29 06:26:02
【问题描述】:

我对 Grails 很陌生,但我对 Spring 3 和 Hibernate 有很强的背景。实际上,我只是在玩弄它,看看我能在多大程度上提高中小型项目的生产力。 我正在尝试将旧的 SQLServer-Hibernate-Spring-JSP 应用程序迁移到 Grails,这就是我安装逆向工程插件的原因。虽然让它运行起来很容易,但我现在面临着某种列名的命名约定/策略,我不知道如何解决。 我运行插件为我的 SQL Server 数据库中的单个表(只是为了尝试)生成域类,然后运行“generate-all”来获取控制器和 CRUD 视图。到目前为止一切正常。当我运行应用程序并显示显示所有可用控制器的主视图时,我单击了新生成的控制器,但这会导致我进入一个错误页面,其中显示未找到某个列名。 请看下面生成的域类:

class Documentos {

    String fileName
    Integer fileSize
    byte[] document
    Integer idTipoDocumento
    Boolean visible
    Date dateElaborated
    Date dateApproved
    String state
    String author
    String department
    String scope
    String language
    String codeNumber
    String comments
    Boolean manual
    Boolean hasChecklists

    static mapping = {
        id generator: "assigned"
    }

    static constraints = {
        fileName maxSize: 150
        fileSize nullable: true
        document nullable: true
        idTipoDocumento nullable: true
        visible nullable: true
        dateElaborated nullable: true
        dateApproved nullable: true
        state nullable: true
        author nullable: true
        department nullable: true
        scope nullable: true
        language nullable: true
        codeNumber nullable: true
        comments nullable: true
        manual nullable: true
        hasChecklists nullable: true
    }
}

如果我检查生成的类,一切看起来都很好(除了 SQLServer nvarchar 类型被转换为 Serializable 而不是 String,但我现在可以接受手动替换)。 但是,当 Grails 调用 DocumentosController.groovy 中的 list 方法时,会检索到以下错误:

Error |
2014-08-06 11:20:30,711 [http-bio-8080-exec-2] ERROR util.JDBCExceptionReporter  - El nombre de columna 'code_number' no es válido.
Error |
2014-08-06 11:20:30,718 [http-bio-8080-exec-2] ERROR errors.GrailsExceptionResolver  - SQLServerException occurred when processing request: [GET] /IdeaProjects/documentos/index
El nombre de columna 'code_number' no es válido.. Stacktrace follows:
Message: El nombre de columna 'code_number' no es válido.
    Line | Method
->>  216 | makeFromDatabaseError      in com.microsoft.sqlserver.jdbc.SQLServerException
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|   1515 | getNextResult              in com.microsoft.sqlserver.jdbc.SQLServerStatement
|    404 | doExecutePreparedStatement in com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement
|    350 | doExecute                  in com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement$PrepStmtExecCmd
|   5696 | execute . . . . . . . . .  in com.microsoft.sqlserver.jdbc.TDSCommand
|   1715 | executeCommand             in com.microsoft.sqlserver.jdbc.SQLServerConnection
|    180 | executeCommand . . . . . . in com.microsoft.sqlserver.jdbc.SQLServerStatement
|    155 | executeStatement           in     ''
|    285 | executeQuery . . . . . . . in com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement
|     55 | <init>                     in grails.orm.PagedResultList
|     15 | $tt__index . . . . . . . . in com.DocumentosController
|    200 | doFilter                   in grails.plugin.cache.web.filter.PageFragmentCachingFilter
|     63 | doFilter . . . . . . . . . in grails.plugin.cache.web.filter.AbstractFilter
|    886 | runTask                    in java.util.concurrent.ThreadPoolExecutor$Worker
|    908 | run . . . . . . . . . . .  in     ''
^    662 | run                        in java.lang.Thread

基本上,它表示未找到“code_number”列,但正如您在域类中看到的那样,实际的列名称是 codeNumber。我不明白为什么 Grails 会尝试访问名为“code_number”的列,但我想这可能与命名策略有关,正如我在 Grails site 中看到的那样。我想当您不进行逆向工程时,这种命名策略很好,但我不知道如何针对这种特殊情况修复它。显然,我不想更改我所有的数据库列名。

有什么想法吗?

谢谢!!

编辑:

好的,我已经能够解决问题,尽管我对解决方案不满意。我向生成的类添加了一些显式映射,这解决了这个问题。最后一课应该是这个:

class Documentos {

    String fileName
    Integer fileSize
    byte[] document
    Integer idTipoDocumento
    Boolean visible
    Date dateElaborated
    Date dateApproved
    String state
    String author
    String department
    String scope
    String language
    String codeNumber
    String version
    String comments
    Boolean manual
    Boolean hasChecklists

    static mapping = {
        id generator: "assigned"
        fileName column: "fileName", sqlType: "varchar", length: 150
        fileSize column: "fileSize", sqlType: "int"
        idTipoDocumento column: "idTipoDocumento", sqlType: "int"
        codeNumber column: "codeNumber", sqlType: "nvarchar", length: 4
        version column: "version", sqlType: "nvarchar", length: 4
        dateApproved column: "dateApproved", sqlType: "smalldatetime"
        dateElaborated column: "dateElaborated", sqlType: "smalldatetime"
        hasChecklists column: "hasChecklists", sqlType: "bit"
    }

    static constraints = {
        fileName maxSize: 150
        fileSize nullable: true
        document nullable: true
        idTipoDocumento nullable: true
        visible nullable: true
        dateElaborated nullable: true
        dateApproved nullable: true
        state nullable: true
        author nullable: true
        department nullable: true
        scope nullable: true
        language nullable: true
        codeNumber nullable: true
        comments nullable: true
        manual nullable: true
        hasChecklists nullable: true
    }
}

正如您想象的那样,这不是我对 Grails 的期望。我希望从逆向工程过程中获得一个工作域类,但我得到了一个仍然需要修改的类。我不想为我的数据库中的其他 100 个表执行此操作.......有人知道我是否可以添加某种配置来避免所有这些“手动”映射?

谢谢!!

【问题讨论】:

  • 默认情况下,名为codeNumber 的域类属性将映射到名为code_number 的表列。您是否检查过名为 code_number 的列是否存在?
  • 没有任何 code_number 列名,无论是在 DB 中的表上还是在生成的域类中,正如您在我发布的代码中看到的那样。关键是我正在应用逆向工程,所以没有域字段映射到表名,但反过来。

标签: sql-server spring hibernate grails reverse-engineering


【解决方案1】:

无论您是从数据库生成域类还是从数据库生成域类,两者都必须保持一致。因为您的Documentos 域类有一个名为codeNumber 的属性,所以documentos 数据库表必须有一个名为code_number 的列。

在您的评论中,您表示该列不存在,所以我猜这是错误的原因。

【讨论】:

  • 那我不明白为什么codeNumber 属性意味着匹配的列名应该是code_number。这是 Grails 中的默认行为吗?有什么办法可以改变吗?
猜你喜欢
  • 1970-01-01
  • 2014-07-03
  • 2011-03-12
  • 1970-01-01
  • 2023-03-24
  • 2016-01-20
  • 1970-01-01
  • 2014-08-08
  • 1970-01-01
相关资源
最近更新 更多