Thursday, June 21, 2012

Grails/ Hibernate clean schema

Sometimes you may want to clean up the entire DB. Grails does this for you if you specify create-drop as the datasource dbCreate property, but sometimes (e.g. if you are deploying to a test of prod server, you can't set this to create-drop), you might just want to be able to clean down the database.



One handy script to clear the DB is to run grails schema-export export. This will run the hibernate schema-export ant task, setting the flag to clear the DB. (It will recreate it again after, using the new schema).

If you want to permanently delete the schema you can modify the schema-export and create your own, e.g.

...
target(cleanDb: 'Clean Db using Run Hibernate SchemaExport') {
    depends(packageApp)

    configureFromArgs()

    def file = new File(filename)
    ant.mkdir(dir: file.parentFile)

    configClasspath()
    loadApp()

    populateProperties()

    def configuration = classLoader.loadClass(configClassName).newInstance()
    configuration.setGrailsApplication(grailsApp)
    configuration.setProperties(props)
    def hibernateCfgXml = eventsClassLoader.getResource('hibernate.cfg.xml')
    if (hibernateCfgXml) {
        configuration.configure(hibernateCfgXml)
    }

    def schemaExport = classLoader.loadClass('org.hibernate.tool.hbm2ddl.SchemaExport')
        .newInstance(configuration)
        .setHaltOnError(true)
        .setOutputFile(file.path)
        .setDelimiter(';')

    def action = "Cleaning Db "
    println "${action} in environment '${grailsEnv}' using properties ${props}"


    // 1st drop, warning exceptions
    //schemaExport.execute(stdout, true, true, false)
    schemaExport.drop(true, true)


    if (!schemaExport.exceptions.empty) {
        schemaExport.exceptions[0].printStackTrace()
    }
}




Eager fetching grails and Hibernate

This is taken from grails docs http://grails.org/doc/latest/guide/GORM.html#fetching  
 Basically for single associations use fetch: 'join' (using lazy:false means that there will be 2 sql statements per association.). However for one to many use lazy:false

Configuring Eager Fetching

An alternative approach that avoids the N+1 queries is to use eager fetching, which can be specified as follows:
class Airport {
    String name
    static hasMany = [flights: Flight]
    static mapping = {
        flights lazy: false
    }
}
In this case the flights association will be loaded at the same time as its Airport instance, although a second query will be executed to fetch the collection. You can also use fetch: 'join' instead of lazy: false , in which case GORM will only execute a single query to get the airports and their flights. This works well for single-ended associations, but you need to be careful with one-to-manys. Queries will work as you'd expect right up to the moment you add a limit to the number of results you want. At that point, you will likely end up with fewer results than you were expecting. The reason for this is quite technical but ultimately the problem arises from GORM using a left outer join.
So, the recommendation is currently to use fetch: 'join' for single-ended associations and lazy: false for one-to-manys.
Be careful how and where you use eager loading because you could load your entire database into memory with too many eager associations. You can find more information on the mapping options in the section on the ORM DSL.

Tuesday, June 12, 2012

Maven

Some quick maven tips.

To run some code from a maven project
See this link http://www.vineetmanohar.com/2009/11/3-ways-to-run-java-main-from-maven/

mvn exec:java -Dexec.mainClass="com.vineetmanohar.module.Main" -Dexec.args="arg0 arg1 arg2"

Article explains 2 other ways from mvn pom.xml 

To run unit tests from a maven project
See this link http://maven.apache.org/plugins/maven-surefire-plugin/examples/single-test.html

mvn -Dtest=TestSquare,TestCi*le test
 
(Note can have wildcards in class names)
 
 
Can also specify methods (with wildcards)
mvn -Dtest=TestCircle#test* test
 
To not run tests
I used to use 
mvn -Dmaven.tests.skip install 
 
back when I used maven 2.x. 
However with maven 3, you can skip the entire test phase by this switch
 
mvn -DskipTests=true isntall
 
 

Thursday, June 07, 2012

SSH and Putty

Here's a little time saver for SSH and Putty.

1/ Putty (See http://www.howtoforge.com/ssh_key_based_logins_putty)
Use PuTTYgen to generate a new private/ public keypair
  1. Create a new putty connection
  2. Enter a hostname and a "Saved Sessions" name
    1. Under Connection->Data->Username enter 'username'
    2. Under Connection->Data->SSH->Auth->Private File key for Authentication enter the path of the Private Key
  3. Save the connection
  4. Click Open - You should be logged in without being prompted for user/pass combo.




2/SSH Key Setup for internode SSH
This allows you to ssh between machines without re-logging in
  1. Start a Putty session to each node you wish to reach
  2. Run "ssh-keygen -t rsa" on each one
  3. Append the contents of ~/.ssh/id_rsa.pub to the ~/.ssh/authorized_keys on each of the other machines
You should be able to ssh between each machine (any combo) now without a password.