Rants about Java and other internet technologies by Sam Pullara

Generate JPA (or GORM) classes from your database for Java and Grails

was published on October 14th, 2007 and is listed in Java, Technology

Whether you start with the database or start with code, no one wants to do the other one. Certainly by the DRY principle it is a waste of time and potentially a place where you could introduce bugs into your code. Today Dave and I are releasing a command-line utility that will handle the case where you start with the database and want to use JPA to access it. There are other utilities that do this that are generally built into IDEs, however this one fills the niche for those that want to do it in a more automated fashion and don’t want to edit the actual generated code. In fact, we used a previous version of this tool at Gauntlet throughout the development process to keep our database and JPA classes in sync with one another.

Introducing… dbmapper:

Usage: com.moonspider.dbmap.GenerateConfig
  -type (-t) [String] The type to generate, either 'jpa' or 'gorm' (experimental) (jpa)
  -destinationDirectory (-d) [String] Destination directory
  -url [String] The url of the database
  -pkg (-package) [String] The target package ()
  -user (-u) [String] Database user (sa)
  -password (-p) [String] Database password ()
  -globalExtends (-extends) [String] Class for all Java classes to extend
  -globalImplements (-implements) [String] Class for all Java classes to implement
  -driver [String] Database drive class
  -extension (-ext) [String] File extension for the generated code (java)
  -hibernate [String] Generate hibernate.cfg.xml to this directory
  -jaxb [flag] Enable xml binding generation

By default, the tool has a number of rules built into it that I will call ‘best practices’ at least as far as we are concerned:

  1. Tables should have a primary key column named id and it should auto increment.
  2. Foreign keys should be named ${foreignTableName}_id and be specified in the database.
  3. Many-to-many join tables should be named ${tableName1}_${tableName2}.

If for some reason you want to break one of these rules you will need to dig into the configuration of dbmapper. On the JPA side there are a number of conventions that it uses:

  1. Class and property names are converted from _ separated to CamelCase.
  2. Many-to-one and one-to-one relationships are marked as eager.
  3. One-to-many and many-to-many relationships are marked as lazy.
  4. Relationship collections are suffixed with List rather than making them plural.

Again, these are adjustable through a configuration file that I suggest that you never use unless absolutely necessary. The most typical use case for the configuration file is when a database identifier conflicts with an identifier used in Java or Grails. In this case you can either configure dbmapper or change your database. DBMapper is designed to work well with the dbmigrate utility and in fact I recommend you use them together for the most leverage. It is great to be able to add a new migration, execute the migration, generate new classes and see exactly the effect that your database change has on the domain model.

The default functionality is also available directly from Grails. On the command-line simply type:

grails install-plugin dbmapper

This will contact the plugin repository and install the latest dbmapper plugin directly into your Grails application. Assuming that you have configured your database in the normal fashion for Grails you can then generate domain classes directly from that connection with a single command:

grails generate-domain-classes

Assuming that is successful you will find all of your domain classes in the grails-app/domain directory and also a hibernate configuration file in your grails-app/conf/hibernate directory. You should then be able to use tasks likes generate-all to create views and controllers for each of your domain classes.

There is also experimental support for creating GORM classes instead of JPA classes, however this really is experimental at this time and I suggest that you only try it if you are interested in fixing it. GORM doesn’t seem to have the flexibility dbmapper needs quite yet.

Another feature of dbmapper is the ability to create JAXB annotations on the JPA classes so the objects can be read from and written to XML in addition to the database. The dbmapper framework itself is designed to be reasonably extensible. By adding another template you can extend it to generate mappings to other persistence frameworks.

"Generate JPA (or GORM) classes from your database for Java and Grails" was published on October 14th, 2007 and is listed in Java, Technology.

Follow comments via the RSS Feed | Leave a comment | Trackback URL

  • Hi,

    I've read your article and currently I play with Grails and JPA. When I use both together the application hangs.

    http://stephan.reposita.org/archives/2007/10/15...

    Do you have any ideas? Did you successfully use JPA with Grails?

    Thanks
    -stephan
  • sam
    Hi Stephen,

    The Grails support is tested with the Grail-1.0-RC1 nightly build, not the currently stable release, because there are a number of new features that I needed to leverage. I also just use the built-in Hibernate support rather than trying to call out to the EntityManager myself -- I'm still using GORM, just with my JPA based annotation classes rather than Groovy based GORM classes. The one thing I forgot to note here though is that you have to tell GORM about the annotations:

    import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsAnnotationConfiguration
    dataSource {
    configClass = GrailsAnnotationConfiguration.class

    Otherwise GORM won't see the domain classes. As for using real JPA APIs I haven't tested it. I will try it later and see what I find.

    Sam
  • Parker
    I tried it with Oracle, got an "ORA-00942 Table or View does not exist". Any Ideas ?

    java -classpath .;ojdbc5.jar;dbmap-r12.jar com.moonspider.dbmap.Generator -url jdbc:oracle:thin:@192.168.1.220:1521:mydb -user myuser -password mypass -driver oracle.jdbc.driver.OracleDriver -d mydb
    Error: java.sql.SQLException: ORA-00942: Tabelle oder View nicht vorhanden

    Usage: com.moonspider.dbmap.GenerateConfig
    ...
  • sam

    I tried it with Oracle, got an “ORA-00942 Table or View does not exist”. Any Ideas ?


    java -classpath .;ojdbc5.jar;dbmap-r12.jar com.moonspider.dbmap.Generator -url jdbc:oracle:thin:@192.168.1.220:1521:mydb -user myuser -password mypass -driver oracle.jdbc.driver.OracleDriver -d mydb

    Error: java.sql.SQLException: ORA-00942: Tabelle oder View nicht vorhanden


    Usage: com.moonspider.dbmap.GenerateConfig





    Hi Parker,

    I've added an issue to the tracker on the site: http://code.google.com/p/dbmapper/issues/detail... . Can you rerun the command line with -Ddebug=true and post the stacktrace to the issue that I've opened?

    Thanks,
    Sam
  • Hi Sam,

    thanks for the feedback, I'll try RC1 and see if it works. When you try JPA directly later, it would be nice to drop me a note with
    the result, perhaps on my blog / using mail.

    Thanks
    -stephan
blog comments powered by Disqus

YUI-Mainstream Theme by Buzzdroid.com

 Premium Wordrpess Theme