Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any command line tool that can generate Java entity classes from db (NOT Netbeans or Eclipse wizard)

I used to use Netbeans wizard (version 6.7.1) to generate entity classes from database. Now I want to look for an independent tool (script, command line tool...) that can do the same task, because some developers in my team use Eclipse instead of Netbeans, or Netbeans but of different version (ie 6.9.1 or 7.0...), and those IDE generate entity classes in different ways.

Up to now I haven't found any independent tool like that. Maybe I have missed something. If you know one, please tell me. I appreciate that so much.

like image 399
N. Q. P Avatar asked May 12 '11 02:05

N. Q. P


3 Answers

You can use the CLI (Command Line Interface) version of the Telosys Code Generator

See http://www.telosys.org/cli.html

This tool can be used in association with any kind of IDE

like image 105
lgu Avatar answered Oct 27 '22 16:10

lgu


I found myself in a similar situation, and after searching around for quite a while, the only tool I found that supports this from the command line is Apache OpenJPA.

It takes a bit of configuration to get it to work, but it seems to do the job. It works like this:

  1. Create a .xml file from your existing DB schema using the Schema Tool.
  2. Optionally edit the generated xml to your liking (I run this whole process through a Gradle task, so I used Groovy to delete some unwanted tables from the schema)
  3. Generate JPA entity classes from the .xml using the Reverse Mapping Tool (don't have enough reputation to post more then 2 links, sorry). This tool can also take an optional customizer class that you can use to further customize the generated code.

Even though the documentation for these tools states that it is enough to have a properties.xml file on your classpath to make them work, for me they only worked when I explicitly pointed them to a file with the '-properties' arg.

And here are some code snippets to save anyone reading this some time. This was tested with OpenJPA 2.3.0:

Generate schema xml (from a MSSQL DB in my case, hence the driver is on the classpath):

java -cp openjpa-all-2.3.0.jar;sqljdbc4.jar org.apache.openjpa.jdbc.schema.SchemaTool -properties openjpa.xml -action reflect -file schema.xml

Generate entities from xml:

java -cp openjpa-all-2.3.0.jar org.apache.openjpa.jdbc.meta.ReverseMappingTool -properties openjpa.xml -metadata none -annotations true -nullableAsObject true -useGenericCollections true -pkg {your package} -directory {output directory} schema.xml

Sample openjpa.xml (Again, for a MSSQL DB):

<?xml version="1.0"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0">
  <persistence-unit name="Gaya STG">
    <properties>
      <property name="openjpa.ConnectionURL" value="jdbc:sqlserver://{ip}"/>
      <property name="openjpa.ConnectionDriverName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/>
      <property name="openjpa.ConnectionUserName" value="{username}"/>
      <property name="openjpa.ConnectionPassword" value="{pass}"/>
      <property name="openjpa.Log" value="DefaultLevel=WARN, Tool=INFO"/>
    </properties>
  </persistence-unit>
</persistence>

Sample build.gradle file that contains all the above as tasks (Again, for a MSSQL DB):

import java.util.regex.Pattern

apply plugin: 'java'

dependencies {
    compile "org.apache.openjpa:openjpa-all:2.3.0"
    compile "sqljdbc4:sqljdbc4:sqljdbc4"
}

task cleanSchemaXml(type: Delete) {
    delete file("schema.xml")
}

task generateSchemaXml(type: JavaExec, dependsOn: cleanSchemaXml) {
    classpath = configurations.compile
    main = "org.apache.openjpa.jdbc.schema.SchemaTool"
    args "-properties", getPropertiesFile(),
         "-action", "reflect",
         "-file", "schema.xml"

    doFirst {
        println "Generating schema.xml..."
    }

    doLast {
        println "Done generating schema.xml."
        println "Updating schema.xml..."
        updateSchema()
        println "Done updating schema.xml."
    }
}

task cleanEntities(type: Delete) {
    delete fileTree(dir: "{path/to/your/entities}")
}

task generateEntities(type: JavaExec, dependsOn: [cleanEntities, clean,  generateSchemaXml, jar]) {
    classpath = files(configurations.compile, jar.archivePath)  // Add this module's jar to the executed classpath, so we can use the EntityCustomizer (which is assumed to be in this module).
    main = "org.apache.openjpa.jdbc.meta.ReverseMappingTool"
    args "-metadata", "none",
         "-annotations", "true",
         "-nullableAsObject", "true",
         "-useGenericCollections", "true",
         "-properties", getPropertiesFile(),
//        "-customizerClass", "{path.to.your.EntityCustomizer}",
         "-directory", "{path/to/your/entities}",
         "-pkg", "{your.entity.package}",
         "schema.xml"

    doFirst {
        println "Generating entity classes from schema.xml..."
    }

    doLast {
        println "Done generating entity classes."
    }
}

private String getPropertiesFile() {
    // File is read directly from the file-system, will not work from a Jar.
    return file("src/main/resources/openjpa.xml").getAbsolutePath()
}

private void updateSchema() {
    // Only this schema will be kept.
    final def schemasToKeep = ['dbo']

    // These tables will be removed from the .xml
    final def tablesToRemove = [
        'ReplicationMonitor', 'DDLEvents', 'AuditTrail', 'AuditTrailErrorLog', 'sysdiagrams', 'table_relations',
        'tasks_queue', 'tasks_queue_archive',
        '.*history'    // Remove all tables ending with 'history'.
    ].collect { Pattern.compile(it) }

    final File xmlFile = file('schema.xml')

    // Read xml.
    final def xml = new XmlParser().parse(xmlFile)

    // Remove all unnecessary schemas.
    filterSchemas(xml, schemasToKeep)

    // Remove all unnecessary tables.
    filterTables(xml, tablesToRemove)

    // Save updated xml file.
    new XmlNodePrinter(new PrintWriter(new FileWriter(xmlFile))).print(xml)
}

private void filterSchemas(Node xml, List<String> schemasToKeep) {
    final List<Node> removedSchemas = []
    xml.each { schema ->
        final String name = schema.@name
        if (!schemasToKeep.contains(name)) {
            println("Removing schema: $name")
            removedSchemas += schema
        }
    }
    removedSchemas.each { xml.remove(it) }
}

private void filterTables(Node xml, List<Pattern> tablesToRemove) {
    xml.each { schema ->
        final List<Node> removedTables = []
        schema.each { table ->
            final String name = table.@name
            if (tablesToRemove.any { it.matcher(name).matches() }) {
                println("Removing table: $name")
                removedTables += table
            }
        }
        removedTables.each { schema.remove(it) }
    }
}
like image 40
Yevgeny Krasik Avatar answered Oct 27 '22 18:10

Yevgeny Krasik


For Eclipse users, you should use an Eclipse plugin like "Telosys Tools" (http://marketplace.eclipse.org/content/telosys-tools )

It does what you want : connect to a database, retrieve the schema and generate any kind of source files like JPA entities See tutorials : https://sites.google.com/site/telosystutorial/

JPA templates are here : https://github.com/telosys-tools/persistence-jpa-TT210-R2

like image 3
rlopez Avatar answered Oct 27 '22 18:10

rlopez