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)
<%
}
}
%>
}
}
發佈了16 篇原創文章 · 獲贊 0 · 訪問量 2515
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章