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)
<%
        }
    }
%>
    }
}

你可能感兴趣的:(oracle,ant,Sybase,grails,groovy)