`
dellsoft
  • 浏览: 113327 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

grails 根据数据库自动生产 domains

阅读更多
GenerateDataabase.groovy
import java.lang.reflect.Method
import com.pansoft.extjs.DbunitDatabaseTemplateGenerator
import java.sql.Connection
import java.sql.DriverManager

/*
* Copyright 2004-2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
 * Gant script that handles the creation of domain classes from an existing database
 *
 * @author dellsoft
 *
 * @since 1.0
 */

grailsAppName = ""

Ant.property(environment: "env")
grailsHome = Ant.antProject.properties."env.GRAILS_HOME"

includeTargets << new File("${grailsHome}/scripts/Compile.groovy")

//pluginHome = new File("./plugins").listFiles().find {
//    it.name.startsWith('dbmapper-')
//}

target('default': "Generates code for all the domain classes in the database") {
    depends(promptForTableName,generateDomainClasses)
}

target(promptForTableName: "指定表名----") {
    if (!args) {
        Ant.input(addProperty: "artifact.name", message: "请输入表名:\nALL --代表所有")
        args = Ant.antProject.properties."artifact.name"
    }
}

target('generateDomainClasses': "Generate for all all the domain classes in the database") {
    profile("compiling config") {
        compile()
    }

    profile("creating config object") {
        ClassLoader contextLoader = Thread.currentThread().getContextClassLoader()
        classLoader = new URLClassLoader([classesDir.toURL()] as URL[], contextLoader)
        def configSlurper = new ConfigSlurper(grailsEnv)
        def configFile = new File("${basedir}/grails-app/conf/Config.groovy")
        if (configFile.exists()) {
            try {

                config = configSlurper.parse(classLoader.loadClass("Config"))
                config.setConfigFile(configFile.toURL())
            }
            catch (Exception e) {
                e.printStackTrace()

                event("StatusFinal", ["Failed to compile configuration file ${configFile}: ${e.message}"])
                exit(1)
            }

        }
        def dataSourceFile = new File("${basedir}/grails-app/conf/DataSource.groovy")
        if (dataSourceFile.exists()) {
            try {
                def dataSourceConfig = configSlurper.parse(classLoader.loadClass("DataSource"))
                config.merge(dataSourceConfig)
            }
            catch (Exception e) {
                e.printStackTrace()

                event("StatusFinal", ["Failed to compile data source file $dataSourceFile: ${e.message}"])
                exit(1)
            }
        }
        classLoader = contextLoader;
    }

    profile("generate the classes") {
        def username = config.dataSource.username
        def password = config.dataSource.password
        def databaseUrl = config.dataSource.url
        def driver = config.dataSource.driverClassName
        def sqlType
        def tableName = args
        if (driver.indexOf("sybase", 1) > 0) {
            sqlType = "sybase"
        } else if (driver.indexOf("mysql", 1) > 0) {
            sqlType = "mysql"
        } else if (driver.indexOf("oracle", 1) > 0) {
            sqlType = "oracle"
        } else if (driver.indexOf("hsql", 1) > 0) {
            sqlType = "hsql"
        }
        try {
            Class.forName(driver)

            Connection connection = DriverManager.getConnection(databaseUrl, username, password)
            connection.setAutoCommit true
            def generator = new DbunitDatabaseTemplateGenerator()
            println("tableName="+Arrays.asList(tableName).toString())
            println("tableName="+tableName)
            generator.generateDomainClasses(connection,sqlType,'','.',Arrays.asList(tableName))
            println("sqlType="+sqlType)

        } catch (Exception e) {
            e.printStackTrace()

            event("StatusFinal", ["Failed to generate domain classes: ${e.message}"])
            exit(1)
        }
        println("Successfully generated domain classes")
    }
}



DbunitDatabaseTemplateGenerator.groovy

package com.pansoft.extjs

import org.codehaus.groovy.grails.scaffolding.DefaultGrailsTemplateGenerator
import org.codehaus.groovy.grails.commons.GrailsDomainClass
import groovy.text.*;
import org.apache.commons.logging.Log;
import org.springframework.core.io.*
import org.apache.commons.logging.LogFactory;
import org.codehaus.groovy.grails.commons.GrailsDomainClass;
import org.codehaus.groovy.grails.commons.GrailsApplication;
import org.codehaus.groovy.grails.scaffolding.GrailsTemplateGenerator;
import org.codehaus.groovy.grails.commons.GrailsClassUtils as GCU
import org.codehaus.groovy.grails.commons.ApplicationHolder
import java.sql.Connection
import org.dbunit.database.IDatabaseConnection
import org.dbunit.ext.mssql.MsSqlConnection
import org.dbunit.dataset.IDataSet
import org.dbunit.ext.mysql.MySqlConnection
import org.dbunit.ext.oracle.OracleConnection
import org.dbunit.ext.hsqldb.HsqldbConnection
import org.dbunit.dataset.ITableMetaData
import org.dbunit.database.DatabaseConnection;
import org.dbunit.dataset.datatype.*
import java.sql.DatabaseMetaData
import java.sql.ResultSet;
/**
 * Created by IntelliJ IDEA.
 * User: dellsoft
 * Date: 2008-5-21
 * Time: 10:18:13
 * To change this template use File | Settings | File Templates.
 */
class DbunitDatabaseTemplateGenerator extends DefaultGrailsTemplateGenerator {
    static final Log Dbunitlog = LogFactory.getLog(DbunitDatabaseTemplateGenerator.class);

    public IDatabaseConnection conn
    public IDataSet dataSet
//    public String[] tables
    def tables = []
    public DatabaseMetaData databaseMetaData
    def indexColumns = []
    public ResultSet resultSet

    // 定义对应的数据类型
    def dataType = {column ->
//        def column = property
//        def cp = domainClass.constrainedProperties[property.name]

        if (!renderEditorTemplate) {
            // create template once for performance
            def templateText = getTemplateText("dataType.template")
            renderEditorTemplate = engine.createTemplate(templateText)
            Dbunitlog.info("templateText=" + templateText)
        }


        def binding = [column: column]
        Dbunitlog.info("binding=" + binding)
        return renderEditorTemplate.make(binding).toString()
    }

//    public DbunitDatabaseTemplateGenerator(Connection con,String sqlType) {
//
//
//
//    }

    // get the tables from the dataset
    public void generateDomainClasses(Connection conn, String sqlType, String pkg, String destDir, List tableName) {
        switch (sqlType) {
            case 'sybase': this.conn = new MsSqlConnection(conn, null)
                break
            case 'mysql': this.conn = new MySqlConnection(conn, null)
                break
            case 'oracle': this.conn = new OracleConnection(conn, null)
                break
            case 'hsql': this.conn = new HsqldbConnection(conn, null)
                break

        }

        dataSet = this.conn.createDataSet()
        tables = Arrays.asList(dataSet.getTableNames())
        def tableTmp = []
        if (tableName.size() > 0) {
            tableName.each {
                tableTmp << it.toLowerCase()
            }
        }

        if (tableTmp.contains("all")) {

        } else {
            def tmp = [] 
            tmp = tables.findAll {
                tableTmp.contains(it.toLowerCase())
            }.asList()
            tables = tmp
        }

        databaseMetaData = this.conn.getConnection().getMetaData()
        tables.each {
            indexColumns.clear()
            resultSet = databaseMetaData.getIndexInfo(null, this.conn.schema, it, true, false)
//            resultSet = databaseMetaData.getBestRowIdentifier(null, this.conn.schema, it, DatabaseMetaData.bestRowSession, true)
            while (resultSet.next()) {
//                indexColumns['table'] = resultSet.getString(3)
//                indexColumns['unique'] = resultSet.getString(6)
//                indexColumns['type'] = resultSet.getString(7)
                if (resultSet.getString(9) != 'null' && !resultSet.getString(9).is(null)) {
                    indexColumns << resultSet.getString(9)
                }

            }
            generateDomain(dataSet.getTableMetaData(it), pkg, destDir)
        }
        this.conn.close()
    }
    // generate domains from the tables
    public void generateDomain(ITableMetaData tableMetaData, String pkg, String destdir) {
        if (!destdir)
            throw new IllegalArgumentException("Argument [destdir] not specified")

        if (tableMetaData.tableName) {
            Dbunitlog.info("Domain generated at ${tableMetaData.tableName}")
            System.out.println("tableName=" + tableMetaData.tableName)
//            def fullName = domainClass.fullName
//            def pkg = ""
//            def pos = fullName.lastIndexOf('.')
//            if (pos != -1) {
//                // Package name with trailing '.'
//                pkg = fullName[0..pos]
//            }

            def destFile = new File("${destdir}/grails-app/domain/${tableMetaData.tableName[0] + tableMetaData.tableName[1..-1].toLowerCase()}.groovy")
            if (canWrite(destFile)) {
                destFile.parentFile.mkdirs()

                destFile.withWriter {w ->
                    generateDomain(tableMetaData, w)
                }

                Dbunitlog.info("Domain generated at ${destFile}")
            }
        }
    }

    public void generateDomain(ITableMetaData tableMetaData, Writer out) {
        def templateText = getTemplateText("Domain.groovy")

        def binding = [
                tableName: tableMetaData.tableName[0] + tableMetaData.tableName[1..-1].toLowerCase(),
                columns: tableMetaData.columns,
                primaryKeys: tableMetaData.primaryKeys,
                indexColumns: indexColumns,
                dataType: dataType,
                comparator: org.codehaus.groovy.grails.scaffolding.DomainClassPropertyComparator.class]

        def t = engine.createTemplate(templateText)
        t.make(binding).writeTo(out)
    }



    private canWrite(testFile) {
        if (!overwrite && testFile.exists()) {
            try {
                ant.input(message: "File ${testFile} already exists. Overwrite?", "y,n,a", addproperty: "overwrite.${testFile.name}")
                overwrite = (ant.antProject.properties."overwrite.${testFile.name}" == "a") ? true : overwrite
                return overwrite || ((ant.antProject.properties."overwrite.${testFile.name}" == "y") ? true : false)
            } catch (Exception e) {
                // failure to read from standard in means we're probably running from an automation tool like a build server
                return true
            }
        }
        return true
    }

    private getTemplateText(String template) {
        def application = ApplicationHolder.getApplication()
        // first check for presence of template in application
        if (resourceLoader && application?.warDeployed) {
            return resourceLoader.getResource("/WEB-INF/templates/scaffolding/${template}").inputStream.text
        }
        else {
            def templateFile = "${basedir}/src/templates/scaffolding/${template}"
            if (!new File(templateFile).exists()) {
                // template not found in application, use default template
                def ant = new AntBuilder()
                ant.property(environment: "env")
                def grailsHome = ant.antProject.properties."env.GRAILS_HOME"
                templateFile = "${grailsHome}/src/grails/templates/scaffolding/${template}"
            }
            return new File(templateFile).getText()
        }
    }


}


domain.groovy 模板
<% import org.codehaus.groovy.grails.orm.hibernate.support.ClosureEventTriggeringInterceptor as Events %>
<% import org.dbunit.dataset.datatype.* %>
class ${tableName} {
<%
    def excludedColumns = ['id', 'version']
    //out put the column
    String omitPrefix = "F_"
    def outColumns = []
    def primaryFields = []
    def mappingFields = [:]
    def constraintsFields = [:]
    def idColumn = ["F_ID"]
    def isUseIdColumn = true
    def isUseVersionColumn = true
    outColumns = columns.findAll {!excludedColumns.contains(it.columnName)}
    outColumns.each {p ->
        def outName
        outName = getOmitPrefixColumn(p.columnName,omitPrefix)
        mappingFields[outName] = p.columnName
        constraintsFields[outName] = p.nullable
%>
    ${dataType(p)} ${outName}
<%
    }
    primaryKeys.each {p ->
        primaryFields << getOmitPrefixColumn(p.columnName,omitPrefix)
    }

    if (primaryFields.isEmpty()) {
        primaryFields = indexColumns
    }

    public String getOmitPrefixColumn(String orignalColumn,String omitPrefixString) {
        String  omitPrefixColumn
        if (orignalColumn.contains(omitPrefixString)){
            omitPrefixColumn = orignalColumn[omitPrefixString.length()..-1].toLowerCase()
        }else {
            omitPrefixColumn = orignalColumn.toLowerCase()
        }
        return   omitPrefixColumn
    }
    if (isUseIdColumn) {
        primaryFields = idColumn
    }


%>
    static mapping = {
       // table '${tableName}'
      <% if ( !isUseVersionColumn ){ %>
        version false
       <% } %>
      //  id composite: ['${primaryFields.join(', ')}']
<%
    mappingFields.each {key,value ->
%>
        ${key} column: '${value}'
<%
    }
%>                                                      
    }

    static constraints = {
<%
    constraintsFields.each {column ->
    if ("${column.value}" == "noNulls") {
%>
        ${column.key} (nullable: false)
<%
        }
    }
%>
    }
}
分享到:
评论
6 楼 leon1509 2008-11-20  
你好,看完试了一下,我把Domain.groovy文件放到工程的src/java目录下了,把另两个文件放到%grails_home%\script下,然后在工程的要目录执行grails generate-database,提示输入表名:
输完以后,提示:
Welcome to Grails 1.0.4 - http://grails.org/
Licensed under Apache Standard License 2.0
Grails home is set to: D:\grails-1.0.4

Base Directory: E:\workspace\AutoGenerateDomainByDB
Note: No plugin scripts found
Running script D:\grails-1.0.4\scripts\GenerateDataabase.groovy
Environment set to development
请输入表名:
ALL --代表所有
account@dl_idmanage
  [groovyc] Compiling 9 source files to C:\Documents and Settings\Administrator\.grails\1.0.4\projects\AutoGenerateDomainBy
DB\classes
Compilation error: org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed, E:\workspace\AutoGenerat
eDomainByDB\src\java\Domain.groovy: 1: unexpected token: < @ line 1, column 1.
   <% import org.codehaus.groovy.grails.orm.hibernate.support.ClosureEventTriggeringInterceptor as Events %>
   ^

1 error


这是什么原因啊?Domain.groovy文件中怎么有“<%”标签呢?
5 楼 leon1509 2008-11-20  
Domain.groovy模板文件报错啊!这个文件中怎么有<%字符啊?
4 楼 leon1509 2008-11-20  
该如何部署执行啊?
3 楼 RayChase 2008-10-28  
:lol: Great! Groovy发展最需要这样的创新大师
2 楼 sword721 2008-08-21  
存在关联关系的表好像不太好使啊
1 楼 casephoen 2008-08-03  
不错,不知道实践结果感觉如何,呵呵

相关推荐

    Grails Grails Grails

    1. **自动化配置和约定优于配置**:Grails 提供了许多默认配置,例如数据库连接、URL映射等,开发者只需按照约定编写代码即可,减少了配置工作。 2. **GORM(Grails Object Relational Mapping)**: GORM 是Grails...

    grails-用户手册

    Grails支持多语言环境,通过`messages.properties` 文件实现国际化,可以根据用户浏览器设置自动选择对应的语言版本。 总结来说,《Grails用户手册》涵盖了从项目创建到部署运行的全过程,包括Grails的基础概念、...

    使用 Grails 快速开发 Web 应用程序

    Grails的自动化工具如GORM(Grails Object-Relational Mapping)将帮助快速生成数据库操作的代码。 通过本教程,读者将掌握Grails的基本开发技术,包括Groovy语言基础、MVC模式的理解以及Grails框架的核心组件使用...

    Grails案例

    - Groovy语言:Grails是基于Groovy语言的,Groovy是一种动态类型的Java平台上的编程语言,它与Java语法兼容,但提供了更简洁的语法和更高的生产力。 - MVC架构:Grails遵循Model-View-Controller(MVC)设计模式,...

    grails中文入门简介

    此外,还可以配置自动数据库移植功能,它会在应用启动时根据域类(domain class)结构自动创建数据库表。 Grails的命令行工具非常强大,它支持创建Gant脚本来自动化重复的构建任务。用户可以创建可复用的Grails脚本...

    grails中文文档

    此外,了解 Grails 的领域类(Domain Class)是如何映射到数据库的。 3. **GORM 数据库访问**:Grails 的 GORM(Grailed Object Relational Mapping)提供了一个简单易用的 ORM 解决方案,用于与数据库交互。通过...

    Grails企业web应用开发与部署

    3. 创建项目:使用`grails create-app`命令创建新项目,Grails会自动生成项目的目录结构和基础文件。 三、Grails开发实践 1. GORM:Grails的ORM框架,支持关系型数据库如MySQL、PostgreSQL,也支持NoSQL数据库如...

    grails脚手架2次优化

    Grails的脚手架基于GORM(Grails Object Relational Mapping)和Groovy模板引擎,通过解析Domain Class自动构建出Controller、View以及相应的模板文件。在运行时,这些文件负责处理数据的增删改查操作。了解这一工作...

    Grails中文参考手册

    GORM 是 Grails 的内置 ORM 框架,它允许开发者使用 Domain Class 来定义数据模型,并自动提供数据库操作。GORM 支持 Hibernate 和 ActiveJDBC,使得数据库操作更加简单。 **Controllers** Controllers 在 Grails ...

    the definitive guide to grails 2

    在Grails框架中,域模型(Domain Classes)是用于表示业务实体的对象,它们通常映射到数据库中的表。通过GORM(Grails Object Relational Mapping),Grails提供了自动的ORM支持,使得开发者无需编写复杂的SQL语句...

    Grails从入门指南(第二版)

    ”应用,体验Grails的快速开发流程,理解Grails脚手架和自动代码生成。 4. **Grails MVC**:深入理解Model-View-Controller架构,包括Domain Classes(模型)、Controllers(控制器)和Views(视图)的使用。 5. *...

    Grails权威指南.pdf

    - **Domain Classes**:Grails中的领域类定义了数据库表结构,通过GORM自动创建表和字段。 - **Relationships**:支持一对一、一对多、多对多等关系映射,例如belongsTo、hasMany、hasOne等。 - **Criteria API**...

    grails中文参考手册

    Grails遵循一套默认的规约,比如数据库连接、目录结构等,这减少了大量手动配置的需求。然而,当需要自定义时,可以通过`Config.groovy`配置文件进行修改。 5. **运行与测试** - **运行Grails应用**:使用`grails...

    Grails+快速开发+Web+应用程序.pdf

    - **定义Domain Model**:通过`grails create-domain-class`命令快速生成对应的领域模型类。 - **创建Controller**:使用`grails create-controller`生成控制器代码,处理HTTP请求和响应。 - **构建View**:编写GSP...

    使用Grails快速开发Web应用

    - **创建应用**:使用`grails create-app Contact`命令可快速生成名为“Contact”的应用框架,该命令自动生成了标准的项目目录结构,包括但不限于`grails-app`下的`conf`、`controller`、`domain`、`i18n`、`...

    grails入门经典

    在 Grails 中,Domain 类代表数据库中的表,是 ORM(对象关系映射)的核心组件。下面通过具体示例来详细了解如何定义 Domain 类: 1. **Race 类**:表示比赛相关信息。 - **属性**: - `String name`:比赛名称。...

    grails 3.3.2 资源下载

    GORM支持多种数据库,如MySQL、PostgreSQL等,并且提供了一种简洁的Domain Class API,使得数据库操作如同操作对象一样简单。 4. **Grails Command Line Interface (CLI)**: Grails 3.3.2 包含了强大的命令行工具,...

    Grails自定义scaffolding模板

    Scaffolding是Grails为了简化开发流程而提供的特性,它根据数据库中的Domain Class自动创建Controller、View以及相应的GSP页面。这些生成的代码能够帮助开发者快速实现对数据的基本操作,如显示列表、创建新记录、...

    grails-1.3.0.RC2

    Grails 是一个基于 Groovy 语言的开源全栈式Web应用框架,它简化了Java开发流程,提供了丰富的功能集和高效的生产力。Grails 1.3.0.RC2(Release Candidate 2)是该框架的一个重要版本,代表了1.3.0系列的候选发布版...

    grails增删改查(初学者必备)

    - Grails的GORM(Grails Object Relational Mapping)框架会自动创建与Domain类对应的数据库表。运行`grails dbm-gorm-diff`命令生成数据库更改脚本,然后用`grails dbm-update`或`dbm-changelog-sync`命令将这些...

Global site tag (gtag.js) - Google Analytics