Hibernate with MySQL – a beginners guide – part 2
This post is a follow on from my previous post Hibernate with MySQL - a beginners guide - part 1. Having followed part 1, you should have a simple java application that prints 'ok', an ant build script, and downloaded hibernate and the MySQL connector. Now it's time to do something useful!
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.java package 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.
August 1st, 2008 - 18:08
Thanks! Helped a lot! Can’t wait for the thrid part.
August 1st, 2008 - 21:14
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
October 30th, 2008 - 15:25
Very good example, I completed it and got a first wonderful experience with Hibernate.
Thank You
January 3rd, 2009 - 01:50
Thanks for the introduction to using Hibernate with MySQL. I hope you get around to writing some more parts to this series!
March 18th, 2009 - 11:39
Hi, I’m new to Hibernate. I found your tutorial really useful. But, I’m facing an issue: When i try and change code of HibernateUtil.java and change values of subject and body of Blog object and build again using ant.
The new data is inserted successfully, but the old data is removed from the database. Why is this happening when we are doing commit ??
May 7th, 2009 - 04:46
Had many troubles with this. After downloading all the jar files that were given in step 1 to install hibernate, I kept getting different errors and ended up having to add jar for xerces as well.
If you have trouble, keep persisting and eventually you’ll come across the right resource that you are after!
May 29th, 2009 - 10:59
Good tutorial… Nice work.
Thanks.
August 29th, 2009 - 17:53
Hi,
Had troubles, much like trav, but I did get there. A total n00b won’t get there without some hints, so here are some.
First, you need an SFL4J jar in addition to those listed, to make it work. I chose slf4j-simple-1.5.8.jar which I just downloaded from the slf4j web site.
Second, you probably want to change the username and password as listed in the src/hibernate.cfg.xml file. Change it to something that’ll work for your database, otherwise clearly it’s not going to work as it won’t connect to your database. The error is bleeding obvious when you hit this, mind you, but it’s worth pointing out that you *need to change the user credentials for this example to work*.
Third, as someone pointed out in the previous page, running “ant run” won’t work because it’ll try to load a class called events.EventManager, which doesn’t exist. Change the line in build.xml that refers to that class to this instead:
That was about it. Once I’d done those three things and followed the rest of the instructions, it all worked.
It might be worth pointing out that you don’t even need to set up your database table; Hibernate takes care of that for you. Unfortunately, running the example twice will drop the table and create it again, so don’t get confused when you run it three times and wonder why there is only one entry in the table, rather than appending new entries each time.
March 24th, 2010 - 19:42
Please use this line to replace ‘events.EventManager’ entry in build.xml:
java fork=”true” classname=”uk.co.pookey.hibernate.HibernateUtil” classpathref=”libraries”
Kenny’s info is not readable in browser (you can view page source to discover it). Hope it helps.
October 22nd, 2009 - 05:52
This is great friend. Learn hibernate quite easily even with ant….
great work.. keep on….
January 2nd, 2010 - 14:07
Hi All,
I ran into some trouble and got a solution, so thought of sharing this info.
I had to execute the below query to allow the Hibernate to connect to MySQL.
grant all privileges on *.* to root@’RAM’ identified by ‘admin’;
where RAM is my computer name.
Thanks,
Ram
February 22nd, 2010 - 03:54
Thanks! Looking forward to part 3. Really helpful to a noob like me.
March 24th, 2010 - 08:57
Found the tutorial friendly to beginners and very helpful.
I followed the instructions. Added the items Kenny listed.
I got this error ( removed the ” to make it readable:
java fork=”true” classname=”uk.co.pookey.hibernate.HibernateUtil” classpathref=”libraries”
Do you have suggestions for fixing it? Many thanks.
March 24th, 2010 - 08:59
sorry, too tired, had type. my error msg:
Exception in thread “main” java.lang.IllegalAccessError: tried to access field org.slf4j.impl.StaticLoggerBinder.SINGLETON from class org.slf4j.LoggerFactory
Thanks for your help.
March 24th, 2010 - 17:01
Solution:
1. Remove file:
hibernate\lib\slf4j-api-1.5.2.jar
2. Add to your project two new files:
slf4j-api-1.5.11.jar
slf4j-log4j12-1.5.11.jar
Just make sure they are the same version.
It should resolve the above problem.
June 22nd, 2010 - 12:57
Thank you very much. I’ve been through 3 example programs before this and it the first one that worked. No problems at all.
June 24th, 2010 - 13:08
Very useful articles though some dependency issues were there. Also I had given the password as given in
“Schipiaf2
Thinking it was not closed, I used “pwd”. took much time to figure out that this is the reason that the connection was failing
June 24th, 2010 - 13:20
Everytime I run this with modified values, it does not insert new record. Instead it updates the first record it created. I tried setting blog.Id() to a new value. even then it updated the same records where id=1. What’s wrong?
July 6th, 2010 - 20:06
sweet!!..this works like a charm..thanks a lot .
July 24th, 2010 - 09:04
worked fine, juts the [java fork="true" classname="[yourPackage].HibernateUtil” classpathref=”libraries”] issue, and i also mention that i put in my /lib all jars from the hibernate bunddle.
thanks