在啟動Hibernate時,預設會為每個實體類別建立SQL語法,問題在於Hibernate如何知道您新增資料時,哪些資料要新增至欄位中,而更新資料時,又如何預先得知要更新哪些欄位?
其實Hibernate並沒有去預測,它所產生的INSERT語法或UPDATE語法,都是對每個欄位進行操作,即使您INSERT時,有些欄位沒有資料,或UPDATE時,只想更新一個,但Hiberntae所產生的SQL則是將舊資料也用UPDATE語法再更新一次。
舉個簡單的例子,在 第 一個 Hibernate 中,如果您使用以下的類別來進行資料新增與更新:
- 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");
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction tx= session.beginTransaction();
session.save(user);
tx.commit();
session.close();
session = HibernateUtil.getSessionFactory().openSession();
tx= session.beginTransaction();
user = (User) session.get(User.class, new Long(1));
user.setAge(new Long(30));
tx.commit();
session.close();
HibernateUtil.shutdown();
}
}
注意到,新增資料時,age屬性並沒有設定,而更新資料時,也只是增加了age屬性的資料,但觀看所產生的SQL:
Hibernate:
insert
into
T_USER
(name, age)
values
(?, ?)
Hibernate:
select
user0_.id as id0_0_,
user0_.name as name0_0_,
user0_.age as age0_0_
from
T_USER user0_
where
user0_.id=?
Hibernate:
update
T_USER
set
name=?,
age=?
where
id=?
insert
into
T_USER
(name, age)
values
(?, ?)
Hibernate:
select
user0_.id as id0_0_,
user0_.name as name0_0_,
user0_.age as age0_0_
from
T_USER user0_
where
user0_.id=?
Hibernate:
update
T_USER
set
name=?,
age=?
where
id=?
SQL中一視同仁的對每個欄位都進行資料的新增或更新,如果您的表格欄位數很多的話,即使只更新一個屬性,卻需要針對每個欄位的內容全部重新更新,顯然對資料庫來說很沒效率。
您可以考慮在HBM中設定Hibernate動態生成SQL,而不是在啟動Hibernate時就生成SQL語法:
- 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"
dynamic-insert="true"
dynamic-update="true">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="name" column="name"/>
<property name="age" column="age"/>
</class>
</hibernate-mapping>
設定dynamic-insert與dynamic-update為true後,Hibernate會依據實際要新增或更新的欄位,於執行時期動態產生SQL語法,例如若如上設定,執行同一個程式時,將產生以下的SQL語句:
Hibernate:
insert
into
T_USER
(name)
values
(?, ?)
Hibernate:
select
user0_.id as id0_0_,
user0_.name as name0_0_,
user0_.age as age0_0_
from
T_USER user0_
where
user0_.id=?
Hibernate:
update
T_USER
set
age=?
where
id=?
insert
into
T_USER
(name)
values
(?, ?)
Hibernate:
select
user0_.id as id0_0_,
user0_.name as name0_0_,
user0_.age as age0_0_
from
T_USER user0_
where
user0_.id=?
Hibernate:
update
T_USER
set
age=?
where
id=?
當然,動態判斷哪些欄位需要更新,增加了應用程式本身的負擔,但減輕了資料庫的負擔,建議這種方式只用在於有大量欄位的表格之上。