Tuesday, June 20, 2006

So Much for Professional Skills Update

I've been reading up and using the Hibernate 3 persistance model over the last couple of weeks, but I've reached a crossroads. After learning the basics of any technology, you are exposed to a world of applications beyond casual usage. In my case, it seems annotations are my next step. While researching what the heck these are about, I came across a lot of frameworks that support the feature, the most promising being the Spring Framework. I'm not likely to adopt it, unless I have to.
In a world of technology that changes so often, you must keep abreast with the happenings in your specialty. Part of what keeps me competitive is my relentless pursuit and desire to learn any new techniques that crop up in the programming (web, Java, and databases). The big benefit is that most new techniques include tools that make a developer's work easier; so why not adopt whatever helps me be more productive? It's almost a fulltime "job" on its own, and it gets harder when school starts. So on days when I don't wanna socialize, I'll lock myself in my room and get lost in code. Wonder whether it's a good way to spend time, but it certainly helps my hungry brain ...
So, for the next few weeks I will move from Hibernate basics -> Annotations -> EJB3. This path covers the data access and persistance layer of any data-intensive application. Form there, I'll whoosh back to JSF and how to make Oracle's ADF framework work on my JBoss application servers. That effectively covers my need to catch up on servlet/JSP (presentation) technologies. Then I really want to get into graphics on one of two fronts (or both): web media or game programming. I think I'll refresh on some web design concepts too, including the newest craze AJAX.
This is a good time to focus on skill improvement because I have no active projects via Strive (just maintenance), and no school for the summer. I have no idea what will happen when any of that changes. But it won't be more than I can bear, I'm sure.

Tuesday, June 06, 2006

Hibernate: Types and Mapping to Database

After configuring your environment as described here, now you can create your types - Java classes that also double as table structures in the database. We'll work with a simple class, Person, that represents a person.
  1. Create the source Person.java. Add the private properties, and their respective getters and setters, bean style. For the preperty intended to become the primary key of the table, make its setter private. This class is jubz.practice.Person.java, for example.
  2. Create the mapping file, Person.hbm.xml. This maps the fields of the Person class to a table and columns in the database. The mapping file is saved at jubz\practice\Person.hbm.xml (same place as its class file is).
  3. Insert a config mapping in the hibernate.cfg.xml, [mapping resource="jubz/practice/Person.hbm.xml"/], just before the closing [/session-factory] tag. This tells Hibernate where to find the mapping file.
The mapping file (sample):
[?xml version="1.0"?]
[!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"]
[hibernate-mapping]
[class name="jubz.practice.Person" table="PEOPLE"]
[id name="id" column="GUID"]
[generator class="native"/]
[/id]
[property name="age" type="int" column="AGE"/]
[property name="firstname" column="FIRSTNAME"/]
[property name="lastname" column="LASTNAME"/]
[/class]
[/hibernate-mapping]
The mapping file describes which class properties map to which columns in what table, and their types, if any. The GUID column in the PEOPLE table will be the primary key. If you do not specify a (database data) type, Hibernate uses defaults from the dialects. If you do not specify a column, the property name will be used. Beware of naming types the same as special database names, such as "data" and "value".

The HibernateUtil.java class = sets up the sessions:
public class HibernateUtil {
private static final SessionFactory sessionFactory;
static {
try {
// Create the SessionFactory from hibernate.cfg.xml
sessionFactory = new Configuration().configure().buildSessionFactory();
} catch (Throwable ex) {
// Make sure you log the exception, as it might be swallowed
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}

To create a Person record in the database (sample):
Session session = HibernateUtil.getSessionFactory().getCurrentSession(); // Create a session
session.beginTransaction(); // Open the transaction
Long id = (Long)session.save(p); // Save data to the database, obtain id generated
session.getTransaction().commit(); // Commit the data

To list the Persons in the database (sample):
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
List people = session.createQuery("from Person").list();
session.getTransaction().commit();
for (int i = 0; i < people.size(); i++) {
Person p = (Person) people.get(i);
}

Sunday, June 04, 2006

Hibernate: Setting Up for Development

Before you start coding, there are some requisite steps you must take:
  1. Must have a Sun JDK, with %JAVA_HOME% set to point to the JDK install directory. Additionally, PATH must include a pointer to %JAVA_HOME%\bin. We call this {java}. Using 1.5.0_04.
  2. Must have Apache ANT, with %ANT_HOME% set to point to the ANT install directory. Additionally, PATH must include a pointer to %ANT_HOME%\bin. We call this {ant}, my version is 1.6.5.
Download Hibernate 3.0 from JBoss' SourceForge repository. Extract the compressed file a location, the root of which we will call {hibernate}. Copy the following libraries from {hibernate}\lib to {ant}\lib (to make ANT Hibernate-aware for builds):
  1. antlr-2.7.6rc1.jar
  2. junit-3.8.1.jar
The following are libraries that are needed in Eclipse for development. I have a common archives directory, so I added a new /hibernate folder under it, and will call this {archive-hibernate}. Copy these files from {hibernate}\lib to {archive-hibernate}:
  1. antlr-2.7.6rc1.jar
  2. asm.jar
  3. asm-attrs.jar
  4. cglib-2.1.3.jar
  5. commons-collections-2.1.1.jar
  6. commons-logging-1.0.4.jar
  7. dom4j-1.6.1.jar
  8. hibernate3.jar
  9. jaas.jar
  10. jta.jar
  11. junit-3.8.1.jar
  12. log4j-1.2.11.jar
Prepare your JDBC driver. I connect to a Microsoft SQL Server 2000 database using jTDS. If you will run your builds from the console, copy the jtds-1.2.jar library to {hibernate}\lib. Otherwise, have it available in {archives}\jdbc for reference from an IDE.
Using the Enterprise Manager console, I created my database for use in this project. Let's call it [HIBERNATE]. Since I will connect to it using TCP URLs, you should find out what port mssqlserver listens at; mine is 1433, the default.

At this point, we can open Eclipse (or an IDE of your choice) and create our project. I'll call the project directory {project}. Before coding, we need to reference libraries needed for Hibernate and data access: include all Jars in {archives}\hibernate and {archives}\jdbc in the classpath. Then create the basic directory structure as follows:
  • src = where source files and mapping files will exist
    • package.JavaClass.java (the Java class)
    • JavaClass.hbm.xml (at the same level as the class it will map)
  • src\hibernate.cfg.xml (hibernate configuration)
  • src\log4j.properties (logging - just copy this from {hibernate}\etc as is)
  • lib = where all the libraries referenced above - hibernate and JDBC - are stored. As an alternative, rather than reference the {archive}, you could create a library in Eclipse and include these files therein. You can also include other 3rd party libraries needed by your application.
  • build.xml = the ANT build file.
The basic hibernate.cfg.xml file looks like this (replace block brackets with respective angle brackets):
=====
[?xml version='1.0' encoding='utf-8'?]
[!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"]
[hibernate-configuration]
[session-factory]
[!-- Database connection settings --]
[property name="connection.driver_class"]net.sourceforge.jtds.jdbc.Driver[/property]
[property name="connection.url"]
jdbc:jtds:sqlserver://localhost:1433/HIBERNATE;tds=8.0;lastupdatecount=true[/property]
[property name="connection.username"]sa[/property]
[property name="connection.password"]password[/property]
[!-- JDBC connection pool (use the built-in) --]
[property name="connection.pool_size"]1[/property]
[!-- SQL dialect --]
[property name="dialect"]org.hibernate.dialect.SQLServerDialect[/property]
[!-- Enable Hibernate's automatic session context management --]
[property name="current_session_context_class"]thread[/property]
[!-- Disable the second-level cache --]
[property name="cache.provider_class"]org.hibernate.cache.NoCacheProvider[/property]
[!-- Echo all executed SQL to stdout --]
[property name="show_sql"]true[/property]
[!-- Drop and re-create the database schema on startup --]
[property name="hbm2ddl.auto"]update[/property]
[/session-factory]
[/hibernate-configuration]
Basically, this configuration file defines the database connection parameters to the SQL database. Later, we will only need to add references to mapping files when we start developing code.

The next file is the ANT build file, which looks like this (replace block quotes with appropriate angle brackets):
[project name="hibernate-project-name" default="compile"]
[property name="sourcedir" value="${basedir}/src"/]
[property name="targetdir" value="${basedir}/build"/]
[property name="librarydir" value="${basedir}/lib"/]
[path id="libraries"]
[fileset dir="${librarydir}"]
[include name="*.jar"/]
[/fileset]
[/path]
[target name="clean"]
[delete dir="${targetdir}"/]
[mkdir dir="${targetdir}"/]
[/target]
[target name="compile" depends="clean, copy-resources"]
[javac srcdir="${sourcedir}"
destdir="${targetdir}"
classpathref="libraries"/]
[/target]
[target name="copy-resources"]
[copy todir="${targetdir}"]
[fileset dir="${sourcedir}"]
[exclude name="**/*.java"/]
[/fileset]
[/copy]
[/target]
[target name="run" depends="compile"]
[java fork="true" classname="package.MainClass" classpathref="libraries"]
[classpath path="${targetdir}"/]
[/java]
[/target]
[/project]
This file will instruct ANT to clean, compile, copy resources, and run the MainClass. At this point, your project is set up to run. I will discuss the *.hbm.xml file and inserting a reference to it in the hibernate.cfg.xml file in code samples that I may post. Otherwise, the Hibernate Tutorial is the go-to resource to start using right away. It explains in a little bit more detail what everything we have done here means.

Saturday, June 03, 2006

Do You Hibernate?

The newest technology on the block in terms of data access from relational databases is Hibernate, currently in version 3.x. I've heard a lot about it, but I hadn't really programmed with it. Today I finally started, and I must say it is a whole lot simpler than session/CMP EJBs I've had to write in the past. Best of all, I can still use my favorite database (Microsoft SQL Server 2000) and JDBC driver (jTDS). Also, there is a whole lot less code to write: only 3 Java classes, a couple of configuration files, and an ANT build file.
Most libraries required come with the Hibernate download, but surprisingly, the hibernate3.jar library is not included. I had to download it separately. In the next few posts, I'll be working on creating schemas, modifying schemas, creating/deleting/updating tables, and working with JDBC connection properties (pools and sessions, optimization).
Some basic requirements to get rolling:
  1. JDK 5.0 SE.
  2. Apache ANT (needs additional libraries from Hibernate)
  3. Hibernate itself.
I expect to convert my current EJB-based data models in current projects (yes, including my favorite Jaspora) to Hibernate data access by the end of August 2006, so I'm on a roll. Just need to gain enough experience with the technology before it becomes a business initiative.