Sponsored Link •
Discussion on modeling, its advantages, using either UML or ER. A solution using Maven is provided to provide a work flow using ER modeling.
There's a lot of power attached - especially in recent years - to the notion that you can write a few classes and have a DAO, table schema, web page view, and more generated. The testament to this is Ruby On Rails, where the ActiveRecord model class is the all-powerful, canonical source of everything in the stack. I agree with the notion that there should be one source for the design - where it makes sense - but I don't see any value in making that source the classes used to model the entities in the system, especially if the entity class is destined to be but a language level construct for interfacing with a database.
I model my entities using tools, if I have a choice. It solves a lot of problems. The first, and most certainly least relevant: it generates the pretty picture management will want to see when it comes time to do design documents. Instant management-karma! Modeling provides your mind with a bird's eye-view of your domain model so you can more readily see interplay among your entities, or violations of your normalized forms. Modeling provides also facilitates DRY, because - with a little work - you can come up with a work flow that makes the model the canonical design, and all other artifacts are generated from that.
A tangential effect to modeling is that you avoid having to express the database schema in terms of Hibernate's various mapping methodologies, which is important because Hibernate will let you take advantage of features that don't get expressed in DDL, but in memory. Further, your domain model will hopefully, usually, and likely, outlive your Hibernate code.
Modeling presents the involved with many choices. The first one: whether to use Entity-Relational diagrams or UML diagrams. I've used both.
One recipe with which I've had quite a bit of success involved two sheep sacrifices, AndroMDA, the AndroMDA EJB3 plugin, and Maven. It worked quite well for my work flow, though the feedback cycle was very slow. The process: model in Magic Draw (or whatever tool you prefer), output to XMI, and use the Maven plug in to generate the Hibernate (I should say "JPA", as these are JPA annotated) entities from the XMI files. Run the application that actually uses the entity classes to have the Hibernate tool create/update the table's schema. Occasionally, I had an extra step: run another Maven projects build to have it auto-generate the ActionScript AMF classes from the compiled .class files for the entities. This was useful if you wanted to neatly expose Hibernate entities to your Flex/Flash client.
This took all of about two minutes or so, even if I was just trying to add one field to the entity. Naturally, this fact along was compelling incentive-enough to sit and really think through modifying the diagram: it's too painful to do for something that didn't merit it!
This approach also provided no good way to override the construction of the classes, that I could see, so adding things like Hibernate Search annotations was impossible. (Naturally, there are alternatives in that specific case, like Compass, but you can see my point). That approach fails to take into account that your was using a tool that models object oriented relationships, not schema, to model schema. I rarely mode objects. I model physical model for a database. Expressing that physical model in terms of Hibernate was a secondary or tertiary concern.
My recipe for ER seems to be the most productive, so I'll share that one here. Naturally, any feedback's appreciated! It's so simple, it's deceptive. Use an ER tool. There are many, many, many tools out there. A very smart person I knew swore by, and bought - of his own cash - a copy of CA's ERWin. There are many other tools that are both proprietary and open source. For our purposes, something simple is fine, so long as you can export DDL to your database of choice. I recommend using Power Architect, which is fine for this example.
Use it to build your model. There's a lot to know about ER modeling, not the least of which is that ER itself has many different syntaxes. A great introduction is Beginning Relational Data Modeling, by Sharon Allen and Even Terry. I bring this point up because the syntax ("crow's feet") used in PowerArchitect is different than that of what's used in the book (IDEF1X). Export the model to your database - you do so by configuring a source connection and then using the icon with the word 'SQL' on it. Then run your Maven build against that schema.
What follows is the XML you'll need for your Maven project, as well a the sample
.properties file you'll need to get this to all work. The parts in bold are the part that're doing the magic. Configure those. In the case of the properties file, I include a lot of commented configuration, for your experimentation only. The part that's in bold is what you need to configure to your liking.
Your directory structure should look like:
pom.xml src/main/resources/hibernate.propertiesUsing it - once you have everything setup - is as simple as
mvn clean compile hibernate3:hbm2java. Verify that it produced classes by checking the
The Maven POM
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>group</groupId> <artifactId>artifact</artifactId> <packaging>jar</packaging> <version>1.0-SNAPSHOT</version> <profiles> <profile> <id>group-artifact</id> <dependencies></dependencies> </profile> </profiles> <dependencies> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate</artifactId> <version>3.2.5.ga</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>3.3.1.ga</version> </dependency> <dependency> <groupId>javax.persistence</groupId> <artifactId>persistence-api</artifactId> <version>1.0</version> <scope>compile</scope> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.5</source> <target>1.5</target> </configuration> </plugin> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>hibernate3-maven-plugin</artifactId> <version>2.0-alpha-2</version> <configuration> <components> <component> <name>hbm2java</name> </component> </components> <componentProperties> <implementation>jdbcconfiguration</implementation> <export>true</export> <jdk5>true</jdk5> <ejb3>true</ejb3> </componentProperties> </configuration> <dependencies> <dependency> <artifactId>postgresql</artifactId> <groupId>postgresql</groupId> <version>8.1-404.jdbc3</version> </dependency> </dependencies> </plugin> </plugins> </build> <repositories> <repository> <id>jboss</id> <url>http://repository.jboss.com/maven2</url> <releases></releases> <snapshots> <enabled>false</enabled> </snapshots> </repository> <repository> <id>jboss-snapshot</id> <url>http://snapshots.jboss.org/maven2</url> <releases></releases> <snapshots></snapshots> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>codehaus-plugins</id> <url>http://repository.codehaus.org/org/codehaus/mojo/</url> <releases></releases> <snapshots> <enabled>false</enabled> </snapshots> </pluginRepository> <pluginRepository> <id>jboss-plugins</id> <url>http://repository.jboss.com/maven2</url> <releases></releases> <snapshots> <enabled>false</enabled> </snapshots> </pluginRepository> <pluginRepository> <id>jboss-snapshot-plugins</id> <url>http://snapshots.jboss.org/maven2</url> <releases></releases> <snapshots></snapshots> </pluginRepository> </pluginRepositories> </project>
Relevant Properties File
hibernate.query.substitutions true 1, false 0, yes 'Y', no 'N' hibernate.dialect org.hibernate.dialect.PostgreSQLDialect hibernate.connection.driver_class org.postgresql.Driver hibernate.connection.url jdbc:postgresql://your_host/your_db hibernate.connection.username your_user hibernate.connection.password your_pw hibernate.connection.shutdown=true hibernate.connection.pool_size 1 hibernate.proxool.pool_alias pool1 hibernate.max_fetch_depth 1 hibernate.jdbc.batch_versioned_data true hibernate.jdbc.use_streams_for_binary true hibernate.cache.provider_class org.hibernate.cache.EhCacheProvider
Have an opinion? Be the first to post a comment about this weblog entry.
|Josh Long (http://www.joshlong.com) is an enterprise architect, consultant, and author. When he's not hacking on code, he can be found at the local Java User Group or at the local coffee shop. Josh likes solutions that push the boundries of the technologies that enable them. His interests include scalability, BPM, grid processing, mobile computing and so-called "smart" systems.|