In this part, we're going to create a simple class called 'Blog' which will store blog posts. It will have a subject, a body, and a created date.
Setting up and installing MySQL is not something I'm going to cover here, so I'll assume you have a running MySQL server. Create yourself a database now for hibernate to use. In this example my database name is simply 'hibernate'.
Creating the Blog class
Create a class to hold information about a blog post, I put this in src/uk/co/pookey/Blog.java
package uk.
co.
pookey;
import java.util.Date;public class Blog
{ private Long id;
private String subject;
private String body;
private Date createdAt;
public Long getId
() { return id;
} public void setId
(Long id
) { this.
id = id;
} public String getSubject
() { return subject;
} public void setSubject
(String subject
) { this.
subject = subject;
} public String getBody
() { return body;
} public void setBody
(String body
) { this.
body = body;
} public Date getCreatedAt
() { return createdAt;
} public void setCreatedAt
(Date createdAt
) { this.
createdAt = createdAt;
}}
Unit Testing
To unit test our new class, we'll use testNG (mostly because the junit site was broken at time of writing!). First we need to modify our ant build script. This will allow us to run tests simply by running 'ant test'. When developing an application, it is vitally important you make it as easy as possible to run the tests, otherwise you'll not bother to do it. Here is the extra snippet that needs adding:
<taskdef name="testng" classname="com.beust.testng.TestNGAntTask" classpathref="libraries" />
<target name="test" depends="compile">
<testng sourcedir="${sourcedir}" outputDir="${targetdir}" verbose="2">
<classpath>
<pathelement path="${targetdir}" />
</classpath>
<classfileset dir="${targetdir}" includes="**/*Test.class" />
</testng>
</target>
Now lets download and install testng
$ cd lib
$ wget "http://testng.org/testng-5.7.zip"
$ unzip testng-5.7.zip
$ cp testng-5.7/*.jar .
All we need to do now is write our tests for the Blog class.
package uk.
co.
pookey;
import uk.co.pookey.Blog;import java.util.Date;import org.testng.annotations.*;public class BlogTest
{ @Test
public void setIdTest
() { Blog b =
new Blog
();
b.
setId(new Long(10));
assert
(b.
getId() ==
10) :
"ID was not returned as expected";
} @Test
public void setBodyTest
() { Blog b =
new Blog
();
b.
setBody("this is a test");
assert
"this is a test".
equals(b.
getBody());
} @Test
public void setSubjectTest
() { Blog b =
new Blog
();
b.
setSubject("this is a test");
assert
"this is a test".
equals(b.
getSubject());
} @Test
public void setCreatedAtTest
() { Blog b =
new Blog
();
Date d =
new Date();
b.
setCreatedAt(d
);
assert d.
equals(b.
getCreatedAt());
}}
Finally, we'll run our test to make sure everything is working as expected.
$ ant test
Buildfile: build.xml
clean:
[delete] Deleting directory /home/pookey/hibernate/bin
[mkdir] Created dir: /home/pookey/hibernate/bin
copy-resources:
[copy] Copying 1 file to /home/pookey/hibernate/bin
[copy] Copied 4 empty directories to 2 empty directories under /home/pookey/hibernate/bin
compile:
[javac] Compiling 3 source files to /home/pookey/hibernate/bin
[javac] warning: [path] bad path element "/usr/share/ant/lib/xml-apis.jar": no such file or directory
[javac] warning: [path] bad path element "/usr/share/ant/lib/xercesImpl.jar": no such file or directory
[javac] warning: [path] bad path element "/usr/share/ant/lib/xalan.jar": no such file or directory
[javac] 3 warnings
test:
[testng] [Parser] Running:
[testng] Ant suite
[testng]
[testng] PASSED: setCreatedAtTest
[testng] PASSED: setIdTest
[testng] PASSED: setBodyTest
[testng] PASSED: setSubjectTest
[testng]
[testng] ===============================================
[testng] Ant test
[testng] Tests run: 4, Failures: 0, Skips: 0
[testng] ===============================================
[testng]
[testng]
[testng] ===============================================
[testng] Ant suite
[testng] Total tests run: 4, Failures: 0, Skips: 0
[testng] ===============================================
[testng]
Time to hibernate
First, we need to copy over the required Jar files into our lib folder - you should have downloaded hibernate in part 1, so all you need to do is copy the following:
cp lib/hibernate-3.2/hibernate3.jar lib/
cp lib/hibernate-3.2/lib/dom4j-1.6.1.jar lib/
cp lib/hibernate-3.2/lib/commons-logging-1.0.4.jar lib
cp lib/hibernate-3.2/lib/commons-collections-2.1.1.jar lib
cp lib/hibernate-3.2/lib/jta.jar lib/
cp lib/hibernate-3.2/lib/log4j-1.2.11.jar lib/
cp lib/hibernate-3.2/lib/cglib-2.1.3.jar ./lib
cp lib/hibernate-3.2/lib/asm.jar ./lib/
Hibernate has several ways to configure it's connection properties, in this example we're going to use an XML config file. Here is an example of this file, which should be created in src/hibernate.cfg.xml
<?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>
<property name="connection.url">jdbc:mysql://localhost/hibernate</property>
<property name="connection.username">root</property>
<property name="connection.password">"Schipiaf2</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<property name="hbm2ddl.auto">create</property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property>
<property name="current_session_context_class">thread</property>
<!-- Mapping files will go here.... -->
</session-factory>
</hibernate-configuration>
The next step is to tell hibernate about our Blog class. Again we're going to do this using a xml file, src/uk/co/pookey/Blog.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping>
<class name="uk.co.pookey.Blog" table="blog">
<id name="id" column="id" type="java.lang.Long">
<generator class="increment"/>
</id>
<property name="subject" />
<property name="body" />
<property name="createdAt" />
</class>
</hibernate-mapping>
Having created this file, we need to add it to the hibernate.cfg.xml file just below the comment.
<!-- Mapping files will go here.... -->
<mapping resource="uk/co/pookey/Blog.hbm.xml" />
Modify your HibernateUtil class (src/uk/co/pookey/hibernate/HibernateUtil.java) created in part 1 to this:
$ cat src/uk/co/pookey/hibernate/HibernateUtil.
javapackage uk.
co.
pookey.
hibernate;
import org.hibernate.SessionFactory;import org.hibernate.Session;import org.hibernate.Transaction;import org.hibernate.cfg.Configuration;import uk.co.pookey.Blog;public class HibernateUtil
{ private static org.
hibernate.
SessionFactory sessionFactory;
public static SessionFactory getSessionFactory
() { if (sessionFactory ==
null) { initSessionFactory
();
} return sessionFactory;
} private static synchronized void initSessionFactory
() { sessionFactory =
new Configuration
().
configure().
buildSessionFactory();
} public static Session getSession
() { return getSessionFactory
().
openSession();
} public static void main
(String[] args
) { Blog blog =
new Blog
();
blog.
setSubject("My test post");
blog.
setBody("This is the body of my blog post");
blog.
setCreatedAt(new java.
util.
Date());
Session session = getSession
();
Transaction transaction = session.
beginTransaction();
session.
save(blog
);
transaction.
commit();
}}
Now all that remains is to run out application, and watch it insert data into the database!
$ ant run
Buildfile: build.xml
clean:
[delete] Deleting directory /home/pookey/hibernate/bin
[mkdir] Created dir: /home/pookey/hibernate/bin
copy-resources:
[copy] Copying 2 files to /home/pookey/hibernate/bin
[copy] Copied 4 empty directories to 1 empty directory under /home/pookey/hibernate/bin
compile:
[javac] Compiling 3 source files to /home/pookey/hibernate/bin
[javac] warning: [path] bad path element "/usr/share/ant/lib/xml-apis.jar": no such file or directory
[javac] warning: [path] bad path element "/usr/share/ant/lib/xercesImpl.jar": no such file or directory
[javac] warning: [path] bad path element "/usr/share/ant/lib/xalan.jar": no such file or directory
[javac] 3 warnings
run:
[java] log4j:WARN No appenders could be found for logger (org.hibernate.cfg.Environment).
[java] log4j:WARN Please initialize the log4j system properly.
[java] Hibernate:
[java] select
[java] max(id)
[java] from
[java] blog
[java] Hibernate:
[java] insert
[java] into
[java] blog
[java] (subject, body, createdAt, id)
[java] values
[java] (?, ?, ?, ?)
BUILD SUCCESSFUL
Total time: 3 seconds
Checking this output on MySQLs CLI shows that the record was correctly inserted.
mysql> select * from blog;
+----+--------------+----------------------------------+---------------------+
| id | subject | body | createdAt |
+----+--------------+----------------------------------+---------------------+
| 1 | My test post | This is the body of my blog post | 2008-08-01 17:50:28 |
+----+--------------+----------------------------------+---------------------+
1 row in set (0.00 sec)
In part 3 (assuming I get some feedback from the first 2 parts, or get bored enough to do a third part!) I shall cover loading and modifying a persistent object, information on how to increase the logging level, and relationships.
In part 1 and part 2 I showed how to get up and running with hibernate. This part continues from where we left off. I have packaged up all the files form part 2, including all required jars, and the build script. The file is 4.5meg, and is down
Tracked: Aug 01, 22:14