donderdag 5 november 2009

Java + MySQL + Hibernate

Last time I explained how to set up your system so you could feed queries to a MySQL database from your Java application. Now, to make it prettier and easier, I added Hibernate.

Hibernate will let you get and put Java objects from and into the database.

Ok, download Hibernate Core here and maybe read this tutorial for extra information.

I will be using the database table I made in last example, a table named 'phonebook', with contents:

mysql> SELECT * FROM phonebook;
+----+-------+----------+
| id | name | number |
+----+-------+----------+
| 1 | Barry | 555-1234 |
| 2 | Bob | 555-5678 |
+----+-------+----------+
2 rows in set (0.00 sec)


Now, create a new Java project and add the jars of Hibernate Core and the MySQL Connector/J connector. Our project consists of 5 files, which are 1. a SessionFactoryUtil, to connect with our database, 2. a class which describes a entry of the database table, a phonebook entry, 3. a hibernate config file which lets our program connect to the database, 4. a hibernate mapping file, which maps a database row to the object made in 2. and 5. a test class to show (how) it works.

SessionFactoryUtil
This file creates a connection to the database.

package com.example.phonebook;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class SessionFactoryUtil {

private static final SessionFactory sessionFactory = buildSessionFactory();

private static SessionFactory buildSessionFactory() {
try {
// Create the SessionFactory from hibernate.cfg.xml
return new Configuration().configure("hibernate_phonebook.cfg.xml").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;
}
}


The PhoneBookEntry object

package com.example.phonebook;

public class PhoneBookEntry {
private Integer id;
private String name;
private String number;

/*public PhoneBookEntry(String name, String number) {
this.name = name;
this.number = number;
}*/

public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}

public String toString() {
return "Name: " + getName() + " Number: " + getNumber();
}
}


The hibernate config file
I called my file hibernate_phonebook.xml.cfg. I needed to name this file in the SessionFactoryUtil, because by default hibernate looks for the file hibernate.xml.cfg.
In this file, there's all the data to connect to the database.

<?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://192.168.1.74/test2</property>
<property name="connection.username">root</property>
<property name="connection.password">password</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>

<!-- thread is the short name for
org.hibernate.context.ThreadLocalSessionContext
and let Hibernate bind the session automatically to the thread
-->
<property name="current_session_context_class">thread</property>

<!-- this will show us all sql statements -->
<property name="hibernate.show_sql">true</property>

<!-- mapping files -->
<mapping resource="phonebook.hbm.xml" />

</session-factory>
</hibernate-configuration>


The hibernate mapping file
I called this file phonebook.hbm.xml. I maps the database rows to the object PhoneBookEntry.

<?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="com.example.phonebook.PhoneBookEntry" table="phonebook">
<id name="id" column="id" type="java.lang.Integer">
<generator class="increment"/>
</id>
<property name="name" column="name" type="java.lang.String" />
<property name="number" column="number" type="java.lang.String" />
</class>
</hibernate-mapping>


The test
The last file is a test. What it does: create a connection, read all entries from the table in the database, add an entry and display all entries again.

package com.example.phonebook;

import java.util.Iterator;
import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;

public class PhoneBookTest {
public static void main(String[] args) {
listEntries();
PhoneBookEntry entry = new PhoneBookEntry();
entry.setName("Jay");
entry.setNumber("555-8912");
addEntry(entry);
listEntries();
}


private static void listEntries() {
Transaction tx = null;
Session session = SessionFactoryUtil.getSessionFactory().getCurrentSession();
try {
tx = session.beginTransaction();
List entries = session.createQuery("select e from PhoneBookEntry as e").list();
for (Iterator iter = entries.iterator(); iter.hasNext();) {
PhoneBookEntry element = (PhoneBookEntry) iter.next();
System.out.println(element.toString());
}
tx.commit();
} catch (RuntimeException e) {
if (tx != null && tx.isActive()) {
try {
// Second try catch as the rollback could fail as well
tx.rollback();
} catch (HibernateException e1) {
//logger.debug("Error rolling back transaction");
}
// throw again the first exception
throw e;
} else throw e;


}
}

private static void addEntry(PhoneBookEntry entry) {
Session session = SessionFactoryUtil.getSessionFactory().getCurrentSession();
Transaction tx = session.beginTransaction();
session.save(entry);
session.getTransaction().commit();
}
}


The result
After running, the result is

Hibernate: select phonebooke0_.id as id0_, phonebooke0_.name as name0_, phonebooke0_.number as number0_ from phonebook phonebooke0_
Name: Barry Number: 555-1234
Name: Bob Number: 555-5678
Hibernate: select max(id) from phonebook
Hibernate: insert into phonebook (name, number, id) values (?, ?, ?)
Hibernate: select phonebooke0_.id as id0_, phonebooke0_.name as name0_, phonebooke0_.number as number0_ from phonebook phonebooke0_
Name: Barry Number: 555-1234
Name: Bob Number: 555-5678
Name: Jay Number: 555-8912

First, we see the SELECT query and the result, 2 entries. Then we see the INSERT query, and then another SELECT, now with 3 entries. Just as planned.

Of course, this is a very simple example. You could/should include functions to UPDATE and REMOVE entries in the database, and try to catch more Exceptions. This is just the very basics, to see if it works, and if you understand the basics.

1 opmerking:

  1. Creating the database for our struts- hibernate integration by user in the table. The database will contain one table 'tutorials' for holding the tutorials links and descriptions. Here is the complete sql script for setting up the database.

    BeantwoordenVerwijderen