【发布时间】: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