第一個 Hibernate


這邊以一個簡單的單機程式來示範Hibernate的配置與功能,首先作資料庫的準備工作,在MySQL中新增一個demo資料庫,並建立user表 格:
create table T_USER (
    id bigint not null auto_increment,
    name varchar(255),
    age bigint,
    primary key (id)
)


對於這個表格,您有一個User類別與之對應,表格中的每一個欄位將對應至User實例上的Field成員。
  • User.java
package onlyfun.caterpillar;

public class User {
private Long id;
private String name;
private Long age;

// 必須要有一個預設的建構方法
// 以使得Hibernate可以使用Constructor.newInstance()建立物件
public User() {
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Long getAge() {
return age;
}

public void setAge(Long age) {
this.age = age;
}
}

其中id是個特殊的屬性,Hibernate會使用它來作為主鍵識別,您可以定義主鍵產生的方式,這是在XML映射文件中完成,為了告訴 Hibernate您所定義的User實例如何映射至資料庫表格,您撰寫一個XML映射文件檔名是User.hbm.xml,如下所示:
  • User.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="onlyfun.caterpillar.User" table="T_USER">

<id name="id" column="id">
<generator class="native"/>
</id>

<property name="name" column="name"/>

<property name="age" column="age"/>

</class>

</hibernate-mapping>

<class>標籤的name屬性為所映射的物件,而table為所映射的表格;<id>中 column屬性指定了表格欄位。<id>中主鍵的產生方式在這邊設定為"native",表示主鍵的生成方式由Hibernate根據 資料庫Dialect 的定義來決定,之後還會介紹其它主鍵的生成方式。

同樣的,<property>標籤中的column與type都各自指明了表格中欄位與物件中屬性的對應。

建議將映射文件與編譯出來的User.class放在同一個資料夾之中。

接著必須在Hibernate配置文件hibernate.cfg.xml中指明映射文件的位置,如下加入映射文件位置:
  • 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>

....

<!-- 物件與資料庫表格映射文件 -->
<mapping resource="onlyfun/caterpillar/User.hbm.xml"/>

</session-factory>

</hibernate-configuration>

在使用Hibernate之前,必須先讀入hibernate.cfg.xml文件訊息,配置文件訊息在 Hibernate中對應的代表物件是Configuration物件,當中包括了配置文件訊息,您可以從Configuration中建立 SessionFactory物件,顧名思義,SessionFactory是用來建立Session物件,其作用類似於JDBC中的 Connection物件,不過負責更多關於一次資料庫操作會話的功能。

一個應用程式當中通常只需要一個SessionFactory實例,為了方便整個應用取得同一個SessionFactory實例,可以撰寫一個 HibernateUtil類別:
  • HibernateUtil.java
package onlyfun.caterpillar;

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

public class HibernateUtil {
private static SessionFactory sessionFactory;
static {
try {
sessionFactory = new Configuration().configure()
.buildSessionFactory();
} catch (Throwable ex) {
throw new ExceptionInInitializerError(ex);
}
}

public static SessionFactory getSessionFactory() {
return sessionFactory;
}

public static void shutdown() {
getSessionFactory().close();
}
}

HibernateUtil類別在載入JVM後就會新建Configuration、讀入hibernate.cfg.xml,而後建立 SessionFactory實例,您可以藉由其所提供的兩個static方法來取得SessionFactory物件。

接下來撰寫一個測試的程式,這個程式直接以Java程式設計人員熟悉的語法方式來操作物件,而實際上也直接完成對資料庫的操作,程式將會將一筆資料存 入表 格之中:
  • HibernateDemo.java
package onlyfun.caterpillar;

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

public class HibernateDemo {
public static void main(String[] args) {
User user = new User();
user.setName("caterpillar");
user.setAge(new Long(30));

// 開啟Session,相當於開啟JDBC的Connection
Session session = HibernateUtil.getSessionFactory().openSession();
// Transaction表示一組會話操作
Transaction tx= session.beginTransaction();
// 將物件映射至資料庫表格中儲存
session.save(user);
tx.commit();
session.close();

System.out.println("新增資料OK!請先用MySQL觀看結果!");

HibernateUtil.shutdown();
}
}

如您所看到的,程式中只需要直接操作User物件,並進行Session與Transaction的相關操作,Hibernate就會自動完成對資料 庫的 操作,您看不到任何一行JDBC或SQL的陳述。

接著可以開始運行程式,結果如下:
Hibernate:
    insert
    into
        T_USER
        (name, age)
    values
        (?, ?)
新增資料OK!請先用MySQL觀看結果!


執行結果中顯示了Hibernate所實際使用的SQL,由於這個程式還沒有查詢功能,所以要進入MySQL中看看新增的資料,如下:
mysql> SELECT * FROM T_USER;
+----+-------------+------+
| id    | name         | age  |
+----+-------------+------+
|  1    | caterpillar |   30   |
+----+-------------+------+
1 row in set (0.03 sec)