I seem to persistently return to Groovy when wishing to try out ideas in Java. Groovy serves me well as my Java R&D language. In that sense, I don’t care if my code makes it into production, or is even that fast. It has simply served a serious purpose already. And I’ve previously, and hopefully effectively, illustrated the point whilst doing some image processing recently.
Nontheless, performance is, I hear (and having no interest in performing any metrics myself), steadily improving. And the OpenJDK Da Vinci Machine Project has a sub-project for dynamic invocation which should yield significant performance gains for all dynamic languages on the JVM. Current status apparently at 80%!
Damn, an aside already. If you’re interested or at least wondering what we currently have re. invocation, consider
- invokestatic
Invoke a class (
static) method - invokespecial
Invoke instance method
(special handling for superclass, private, and instance initialization method invocations) - invokeinterface
Invoke interface method
- invokevirtual
Invoke instance method; dispatch based on class
All static calls if my terminology is correct. And the new boy is to be
- invokedynamic
dynamically linked (and even re-linked) under program control, methods only known at runtime
Read John Rose if you want the full story. Yes, it’s a new bytecode for calling (dynamically) methods only known at runtime.
Anyway, that’s an aside, and seeing as I just packed the kids into bed, I thought I’d say something about the code I just wrote. Huh – um, the Entity relationships may give you some idea of what preoccupies the mind of a programmer with little kids :-). Oh, and yes, the code is all to do with Java persistence, Groovy style.
And I’m sharing this because the documented examples only went so far.
package alex
import javax.persistence.* // Entity,...
import org.hibernate.cfg.* // instead of into CLASSPATH, Grapes/Ivy will sort
import org.hibernate.annotations.*;
println "start"
// only about 5 MB downloaded into ~\.groovy\grapes
// CONSIDERATION: user does not have to configure (great) versus makes first run a very slow start
// NB: new hibernate has hibernate-jpa-2.0-api-1.0.0.Final.jar
// i.e. JPA 2.0 API for JPA entityManager versus hibernate sessions
// tried 3.5.4-Final with no luck (hibernate-annotations-3.5.4-Final.jar)!
@Grapes([
@Grab(group='org.hibernate', module='hibernate-annotations', version='3.4.0.GA'), // JBoss supported
@Grab(group='org.slf4j', module='slf4j-simple', version='1.4.2'), // simple logging facade (above log4j,commons logging,...)
@Grab(group='hsqldb', module='hsqldb', version='1.8.0.7'), // 2.0 is now out whilst 1.8 out almost 5 yrs = stable...
// 3.13.0.GA is available. Java Programming Assistant: makes Java bytecode manipulation simple AOP / refelection -- MOP
@Grab(group='javassist', module='javassist', version='3.4.GA'), // sub project of jboss
])
// Alternatively both Parent and Child could extend a Person
@Entity
class Parent {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long id
private String firstName;
private String lastName;
String toString() { "$firstName $lastName" }
@ManyToMany
private List<Child> children;
}
@Entity
class Child {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long id
public String firstName
public String lastName
public Integer age
String toString() { "$firstName $lastName $age" }
@ManyToMany
private List<Parent> parents;
}
// this is basically the persistence.xml out of META-INF
def hibProps = [
"hibernate.dialect": "org.hibernate.dialect.HSQLDialect",
"hibernate.connection.driver_class": "org.hsqldb.jdbcDriver",
"hibernate.connection.url": "jdbc:hsqldb:mem:demodb",
"hibernate.connection.username": "sa",
"hibernate.connection.password": "",
"hibernate.connection.pool_size": "1",
"hibernate.connection.autocommit": "true",
"hibernate.cache.provider_class": "org.hibernate.cache.NoCacheProvider",
"hibernate.hbm2ddl.auto": "create-drop", // set up schema each time easier under dev
"hibernate.show_sql": "true", // show what SQL is being generated
"hibernate.transaction.factory_class": "org.hibernate.transaction.JDBCTransactionFactory",
"hibernate.current_session_context_class": "thread"
]
def configureHibernate(props) {
def config = new AnnotationConfiguration()
props.each { k, v -> config.setProperty(k, v) }
config.addAnnotatedClass(Child) // Child.class
config.addAnnotatedClass(Parent) /* added Parent */
return config
}
println "About to configureHibernate(hibProps).buildSessionFactory()!"
def factory = configureHibernate(hibProps).buildSessionFactory() // org.hibernate.cfg.AnnotationConfiguration
println "Got past configureHibernate(hibProps).buildSessionFactory()!"
// Create family
def me = new Parent(firstName:'Alex', lastName:'Garrett')
def mum = new Parent(firstName:'Mummy', lastName:'Garrett')
def aki = new Child(firstName:'Akira', lastName:'Garrett', age:5)
def tig = new Child(firstName:'Taiga', lastName:'Garrett', age:3)
// Groovy saves a lot of time (compare List<Parent> approach!)
aki.parents = [me, mum]
tig.parents = [me, mum]
// Created family ----------------
// Store family
def session = factory.currentSession
def tx = session.beginTransaction()
session.save(me)
session.save(mum)
println "Saved parents!"
session.save(aki)
session.save(tig)
println "Saved children!"
tx.commit()
// stored family
// DB Query (the ORM'ed Database)
// find my boys
session = factory.currentSession
tx = session.beginTransaction()
def kidsOnly = session.createQuery("from Child").list()
println 'Found ' + kidsOnly.size() + ' Boys:'
kidsOnly.each { println it }
// find the parents
def parentsOnly = session.createQuery("from Parent").list()
println 'Found ' + parentsOnly.size() + ' Parents:'
parentsOnly.each { println it }
// find the relationships
def family = session.createQuery("SELECT DISTINCT c, 'child of', p from Child c, Parent p join c.parents").list()
println 'Found ' + family.size() + ' Relationships:'
family.each { println it }
tx.commit()
// DB Queried
println "Done"
I’d really love to know how to use the latest Hibernate release. Maybe a task for another break. I was surprised that the code would not run from within GroovyConsole. But from the commandline, no problem.
$ groovy hibernate.groovy
OF NOTE:
- UML using UMLLet.exe – 5 minutes it’s so intuitive (OK maybe it’s not exactly compliant UML, but who cares, it does the job).
- CONFIGURATION using Grapes. No effort on my part. More time for R&D!
- CODING: Simply Groovy. NO XML!
- FEEDBACK: show_sql: “true” gives enough feedback to generate the final MANY TO MANY query based on the generated / populated tables
And here’s the output generated by a development run. Very cool indeed, and I still have time left over to sleep. A healthy Geek – Life balance.
$ groovy hibernate.groovy
<strong>start</strong>
<strong>About to configureHibernate(hibProps).buildSessionFactory()!</strong>
2 [main] INFO org.hibernate.cfg.annotations.Version - Hibernate Annotations 3.4.0.GA
61 [main] INFO org.hibernate.cfg.Environment - Hibernate 3.3.0.SP1
70 [main] INFO org.hibernate.cfg.Environment - hibernate.properties not found
77 [main] INFO org.hibernate.cfg.Environment - Bytecode provider name : javassist
87 [main] INFO org.hibernate.cfg.Environment - using JDK 1.4 java.sql.Timestamp handling
175 [main] INFO org.hibernate.annotations.common.Version - Hibernate Commons Annotations 3.1.0.GA
645 [main] INFO org.hibernate.cfg.search.HibernateSearchEventListenerRegister - Unable to find org.hibernate.search.event.FullTextIndexEventListener on the clas
spath. Hibernate Search is not enabled.
705 [main] INFO org.hibernate.cfg.AnnotationBinder - Binding entity from annotated class: alex.Child
769 [main] INFO org.hibernate.cfg.annotations.EntityBinder - Bind entity alex.Child on table Child
881 [main] INFO org.hibernate.cfg.AnnotationBinder - Binding entity from annotated class: alex.Parent
884 [main] INFO org.hibernate.cfg.annotations.EntityBinder - Bind entity alex.Parent on table Parent
980 [main] INFO org.hibernate.cfg.AnnotationConfiguration - Hibernate Validator not found: ignoring
992 [main] INFO org.hibernate.connection.DriverManagerConnectionProvider - Using Hibernate built-in connection pool (not for production use!)
995 [main] INFO org.hibernate.connection.DriverManagerConnectionProvider - Hibernate connection pool size: 1
998 [main] INFO org.hibernate.connection.DriverManagerConnectionProvider - autocommit mode: true
1009 [main] INFO org.hibernate.connection.DriverManagerConnectionProvider - using driver: org.hsqldb.jdbcDriver at URL: jdbc:hsqldb:mem:demodb
1012 [main] INFO org.hibernate.connection.DriverManagerConnectionProvider - connection properties: {user=sa, password=****, autocommit=true}
1227 [main] INFO org.hibernate.cfg.SettingsFactory - RDBMS: HSQL Database Engine, version: 1.8.0
1230 [main] INFO org.hibernate.cfg.SettingsFactory - JDBC driver: HSQL Database Engine Driver, version: 1.8.0
1260 [main] INFO org.hibernate.dialect.Dialect - Using dialect: org.hibernate.dialect.HSQLDialect
1271 [main] INFO org.hibernate.transaction.TransactionFactoryFactory - Transaction strategy: org.hibernate.transaction.JDBCTransactionFactory
1276 [main] INFO org.hibernate.transaction.TransactionManagerLookupFactory - No TransactionManagerLookup configured (in JTA environment, use of read-write or tr
ansactional second-level cache is not recommended)
1282 [main] INFO org.hibernate.cfg.SettingsFactory - Automatic flush during beforeCompletion(): disabled
1286 [main] INFO org.hibernate.cfg.SettingsFactory - Automatic session close at end of transaction: disabled
1289 [main] INFO org.hibernate.cfg.SettingsFactory - JDBC batch size: 15
1292 [main] INFO org.hibernate.cfg.SettingsFactory - JDBC batch updates for versioned data: disabled
1296 [main] INFO org.hibernate.cfg.SettingsFactory - Scrollable result sets: enabled
1298 [main] INFO org.hibernate.cfg.SettingsFactory - JDBC3 getGeneratedKeys(): disabled
1303 [main] INFO org.hibernate.cfg.SettingsFactory - Connection release mode: auto
1307 [main] INFO org.hibernate.cfg.SettingsFactory - Default batch fetch size: 1
1310 [main] INFO org.hibernate.cfg.SettingsFactory - Generate SQL with comments: disabled
1312 [main] INFO org.hibernate.cfg.SettingsFactory - Order SQL updates by primary key: disabled
1315 [main] INFO org.hibernate.cfg.SettingsFactory - Order SQL inserts for batching: disabled
1319 [main] INFO org.hibernate.cfg.SettingsFactory - Query translator: org.hibernate.hql.ast.ASTQueryTranslatorFactory
1326 [main] INFO org.hibernate.hql.ast.ASTQueryTranslatorFactory - Using ASTQueryTranslatorFactory
1328 [main] INFO org.hibernate.cfg.SettingsFactory - Query language substitutions: {}
1331 [main] INFO org.hibernate.cfg.SettingsFactory - JPA-QL strict compliance: disabled
1335 [main] INFO org.hibernate.cfg.SettingsFactory - Second-level cache: enabled
1339 [main] INFO org.hibernate.cfg.SettingsFactory - Query cache: disabled
1350 [main] INFO org.hibernate.cfg.SettingsFactory - Cache region factory : org.hibernate.cache.impl.bridge.RegionFactoryCacheProviderBridge
1355 [main] INFO org.hibernate.cache.impl.bridge.RegionFactoryCacheProviderBridge - Cache provider: org.hibernate.cache.NoCacheProvider
1357 [main] INFO org.hibernate.cfg.SettingsFactory - Optimize cache for minimal puts: disabled
1360 [main] INFO org.hibernate.cfg.SettingsFactory - Structured second-level cache entries: disabled
1371 [main] INFO org.hibernate.cfg.SettingsFactory - Echoing all SQL to stdout
1376 [main] INFO org.hibernate.cfg.SettingsFactory - Statistics: disabled
1378 [main] INFO org.hibernate.cfg.SettingsFactory - Deleted entity synthetic identifier rollback: disabled
1382 [main] INFO org.hibernate.cfg.SettingsFactory - Default entity-mode: pojo
1386 [main] INFO org.hibernate.cfg.SettingsFactory - Named query checking : enabled
1446 [main] INFO org.hibernate.impl.SessionFactoryImpl - building session factory
1744 [main] INFO org.hibernate.impl.SessionFactoryObjectFactory - Not binding factory to JNDI, no JNDI name configured
1765 [main] INFO org.hibernate.tool.hbm2ddl.SchemaExport - Running hbm2ddl schema export
1769 [main] INFO org.hibernate.tool.hbm2ddl.SchemaExport - exporting generated schema to database
1783 [main] INFO org.hibernate.tool.hbm2ddl.SchemaExport - schema export complete
<strong>Got past configureHibernate(hibProps).buildSessionFactory()!</strong>
Hibernate: insert into Parent (id, firstName, lastName) values (null, ?, ?)
Hibernate: call identity()
Hibernate: insert into Parent (id, firstName, lastName) values (null, ?, ?)
Hibernate: call identity()
<strong>Saved parents!</strong>
Hibernate: insert into Child (id, age, firstName, lastName) values (null, ?, ?, ?)
Hibernate: call identity()
Hibernate: insert into Child (id, age, firstName, lastName) values (null, ?, ?, ?)
Hibernate: call identity()
<strong>Saved children!</strong>
Hibernate: insert into Child_Parent (Child_id, parents_id) values (?, ?)
Hibernate: insert into Child_Parent (Child_id, parents_id) values (?, ?)
Hibernate: insert into Child_Parent (Child_id, parents_id) values (?, ?)
Hibernate: insert into Child_Parent (Child_id, parents_id) values (?, ?)
Hibernate: select child0_.id as id0_, child0_.age as age0_, child0_.firstName as firstName0_, child0_.lastName as lastName0_ from Child child0_
<strong>Found 2 Boys:</strong>
Akira Garrett 5
Taiga Garrett 3
Hibernate: select parent0_.id as id1_, parent0_.firstName as firstName1_, parent0_.lastName as lastName1_ from Parent parent0_
<strong>Found 2 Parents:</strong>
Alex Garrett
Mummy Garrett
Hibernate: select distinct child0_.id as col_0_0_, 'child of' as col_1_0_, parent1_.id as col_2_0_, child0_.id as id0_0_, parent1_.id as id1_1_, child0_.age as
age0_0_, child0_.firstName as firstName0_0_, child0_.lastName as lastName0_0_, parent1_.firstName as firstName1_1_, parent1_.lastName as lastName1_1_ from Child
child0_ inner join Child_Parent parents2_ on child0_.id=parents2_.Child_id inner join Parent parent3_ on parents2_.parents_id=parent3_.id, Parent parent1_
<strong>Found 4 Relationships:</strong>
[Akira Garrett 5, child of, Alex Garrett]
[Akira Garrett 5, child of, Mummy Garrett]
[Taiga Garrett 3, child of, Alex Garrett]
[Taiga Garrett 3, child of, Mummy Garrett]
<strong>Done</strong>
Alex Garrett: Designer, coder, ranter and writer at www.lexecorp.com
Often seen working the crowds (promotions, soliciting, begging,…) but mostly freelance coding for a meager living.





Pingback: Tweets that mention Persistently Groovy « LEXECORP -- Topsy.com