`
dellsoft
  • 浏览: 110642 次
  • 性别: 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 配置mongodb数据库

    grails 配置mongodb数据库,并实现了用户登录的系统,只要将grails的环境配置好,安装上mongodb,再建立一个数据库ggtest,然后运行即可自动生成相应的集合数据。

    grails开发环境配置及应用开发

    详细讲解grails开发环境配置。 详细讲解grails连接mysql数据库,crud开发

    Grails3配置单独的数据库properties.pdf

    Grails3配置单独的数据库properties.pdf

    Grails Grails Grails

    Grails Grails Grails Grails Grails

    基于Grails的办公自动化系统的研究与实现.pdf

    基于Grails的办公自动化系统的研究与实现.pdf

    基于Grails的办公自动化系统的研究与实现.rar

    基于Grails的办公自动化系统的研究与实现.rar

    Grails权威指南 Grails权威指南

    Grails权威指南Grails权威指南Grails权威指南Grails权威指南Grails权威指南Grails权威指南

    grails3 CAS链接接数据库

    NULL 博文链接:https://youngbrick.iteye.com/blog/2352298

    ds_test.rar_ds test_grails_oracle

    grails 多数据库源访问,分别访问mysql数据库和oracle 数据库

    Grails权威指南

    第4章 grails中的域(domain)  4.1 简化的orm和grails对象关系映射(gorm)  4.2 gorm基础  4.3 设置属性可选  4.4 gorm中的关系  4.5 执行crud操作  4.5.1 创建书签  4.5.2 读取书签...

    Grails1.1中文文档

    当今的Java Web开发技术显得...所有这些都非常易于使用,这得益于 Groovy 语言的强大以及 Domain Specific Languages (DSLs) 的广泛使用。 本文档将带你从Grails入门开始,最终能够使用Grails框架建设Web应用程序。

    Eclipse下搭建Grails项目

    Grails项目的应用越来越多,而对于初学者来说,在Eclipse下搭建Grails项目是一个难题,这个文档将教会你如何搭建Grails项目,希望对你有所帮助。

    Grails入门指南 -- 针对grails1.0.4更新

    Grails入门指南中文pdf -- 针对grails1.0.4更新,附加idea8 开发grails的流程

    grails login

    grails 用户登录的例子,必须登录后才可以查看信息,并且只有admin用户才可以创建用户,此例子,只要将grails 的环境配好,就可以用了,用的是自带的数据库,如果需要mysql 可以更改。

    grails+Xfire webservice

    grails+Xfire webservice

    grails

    grails-2.1.zip.001

    Grails 教程

    如今的Java Web开发对于需求来说已经变得...借助于功能强大的Groovy动态语言和领域特定语言(Domain Specific Language,DSL),以上那些特性变得非常易用。 这篇文档会向你介绍如何使用Grails框架来搭建Web应用程序。

    Grails完全入门课件附带视频下载地址

    嗯,工作使用 ...domain对象开始学习 思考如何实现登录DEMO 标签,自定义标签 。。。。完善中,课程内容看:课件PDF 因为学习时间段,经验欠缺。若有错误请大家谅解 我想针对初学者入门是很有帮助的

    grails实现分页技术

    供初学者使用,在grails中只有list(自动生成)中有分页实现,而自己新增的页面中需自己实现分页,该文档中描述了如何实现分页以及注意点

Global site tag (gtag.js) - Google Analytics