說起hibernate,肯定很多人一肚子苦水谷婆,也肯定很多人滿口稱贊,說大幅提高開發(fā)效率辽聊。
Hibernate是個讓人愛又讓人恨的東西波材。當時Hibernate的創(chuàng)造者的想法非常好,就是利用這個框架來屏蔽數(shù)據(jù)庫的差異身隐,做到無論是mysql、oracle唯灵、sqlserver還是其他贾铝,對開發(fā)都不影響,開發(fā)者只關注業(yè)務處理埠帕。
三種狀態(tài)垢揩,臨時、持久敛瓷、游離
學Hibernate第一個要了解的概念就是Hibernate對象的三種狀態(tài)叁巨。確實非常難以理解,我學了好多年呐籽,也是近些年才慢慢理解的锋勺。我是06年就開始學習Hibernate的蚀瘸,當時是2.0版本,教材是上海交大孫衛(wèi)琴的精通Hibernate庶橱。記憶尤深贮勃,主要是這本書看了好多好多遍,講的太高深苦澀了苏章。
我說一下我對這個狀態(tài)的理解:
- 臨時:
Person person=new Person()
寂嘉,這個person就是臨時狀態(tài),跟數(shù)據(jù)庫無關的枫绅,如果線程結束泉孩,對象被垃圾回收,這個對象也就不存在了并淋。 - 持久:這個好理解寓搬,就是數(shù)據(jù)庫里也有對應的記錄,比如
Person person=session.load(1)
; - 游離:這個比較難理解预伺,舉個例子订咸,比如新增person,執(zhí)行完
session.save(person);
然后還沒有提交數(shù)據(jù)庫酬诀,這個狀態(tài)就是游離狀態(tài)脏嚷,還沒有完全持久化,不過person這個對象已經(jīng)有對應的id主鍵了瞒御。如果繼續(xù)執(zhí)行session.commit();
父叙,那這個對象就變?yōu)槌志没恕?/li>
確實好難理解,說著說著我就暈了肴裙。不過沒關系趾唱,真到用起來,碰到問題自然而然就理解了蜻懦。
對象關聯(lián)關系
對象的關聯(lián)關系有1對1甜癞,1對多,多對1宛乃,多對多悠咱,還分有中間表關聯(lián),沒有中間表關聯(lián)等等多種情況征炼∥黾龋基本一本Hibernate的教程至少三分之一是講這些內容。確實很高深谆奥,以純面向對象的理念來開發(fā)數(shù)據(jù)庫編程眼坏。
不過多數(shù)開發(fā)人員搞不清這些關聯(lián)關系,完全對照著數(shù)據(jù)庫表結構建對象酸些。Hibernate設計之初宰译,是先設計領域模型檐蚜,然后根據(jù)領域模型的關系進行反向工程,推出數(shù)據(jù)庫設計囤屹。咱們一般是不相信Hibernate的領域模型的熬甚,或者不相信自己的設計能力,更相信數(shù)據(jù)庫的設計能力肋坚,都是先建表乡括,然后倒推領域模型,最終出的結果就是四不像了智厌。而且myeclipse工具幫了倒忙诲泌,算是Hibernate的神助攻,推出數(shù)據(jù)庫的反向工具铣鹏。
還有一個問題敷扫,多數(shù)項目都會遇到這個問題,為了簡化開發(fā)诚卸,各個對象的關聯(lián)關系都取消了葵第,只是簡單利用Hibernate 的增刪改的簡化方法,核心的查詢反而沒用到合溺。我曾經(jīng)問很多人卒密,項目用到Hibernate了,好處在哪棠赛?僅僅一句話哮奇,不用寫增刪改sql了。這其實會暴露更多的問題睛约,比如update非全字段鼎俘,僅僅幾個字段怎么處理?Hibernate的好處一點沒用到辩涝,反而額外增加了開發(fā)難度贸伐。
Hibernate調優(yōu)
這基本是所有開發(fā)人員后期面對的一個問題,Hibernate性能有問題怔揩,遇到數(shù)據(jù)量大的表棍丐,查詢有問題,或復雜查詢寫不了沧踏,還得依賴原生sql來完成,比如group by巾钉、left join等等翘狱。所以本該數(shù)據(jù)庫要做的事情,拿到程序里來寫了砰苍,而且寫完讓人看不懂潦匈,確實難懂阱高,因為Hibernate會根據(jù)對象映射關系生成自己的sql,全是別名茬缩,很難理解赤惊。
Hibernate的學習曲線
Hibernate的學習非常高,可以毫不夸張的講凰锡,沒幾個月的時間很難深入理解未舟。但是還有很多項目用這個,原因就是如果業(yè)務邏輯不復雜的話掂为,可以快速開發(fā)裕膀,增刪改查基本都不用寫代碼。我以前做過一個項目勇哗,dao層用的泛型dao昼扛,service層用的泛型service,Controller層用的泛型Controller欲诺,全基于接口編程抄谐,只要建好各個類名,一句話都不用寫扰法,整個功能就完成了蛹含,包括增刪改、分頁迹恐、取單條記錄等等挣惰,超級牛逼啊。這不就實現(xiàn)了無招勝有招嗎殴边,一句代碼不寫憎茂,功能全部完成,而且還不可能出錯锤岸。反過來講竖幔,如果要改一個邏輯,肯定蒙圈是偷,沒代碼改什么叭狻!
說了很多蛋铆,下面還是得寫個例子來講解一下什么是Hibernate的馋评。
pom.xml
添加依賴
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.18</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>3.6.10.Final</version>
</dependency>
<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.12.1.GA</version>
</dependency>
這里版本用的比較老,我也沒辦法刺啦,因為Hibernate變化太快留特,現(xiàn)在都是5點幾版本了,我是好幾年沒用,跟不上時代了蜕青,不過沒關系苟蹈,原理都沒變。
這里強調一下右核,Hibernate3.6以后持久化是基于Hibernate-jpa-2.0,這個東西和WebLogic自帶的有沖突慧脱,強烈建議如果選用Hibernate,一定要先在weblogic部署贺喝,看有沒有問題菱鸥。我有幾次就是掉進坑了
hibernate.cfg.xml 連接數(shù)據(jù)庫的配置
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost/test</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">2</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- Enable Hibernate's automatic session context management <property name="current_session_context_class">thread</property> -->
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">update</property>
<!-- <mapping resource="com/critc/model/Staff.hbm.xml" /> -->
<mapping class="com.critc.model.Staff" />
</session-factory>
</hibernate-configuration>
這里面的屬性都比較好理解,稍微看下書就能明白意思搜变。
model
@Entity
@Table(name = "staff")
public class Staff {
private int id;
private String name;//
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
這里是采用注解來實現(xiàn)的采缚,現(xiàn)在都采用注解了,配置的時代早過去了挠他。
記住幾點扳抽,必須有@ID,字段的注解盡量寫在get方法上殖侵,當時講過原因贸呢,不過寫在字段上更好理解一些,也起作用拢军。
具體操作類
public class HibernateTest {
public static void main(String[] args) {
Configuration cfg = new Configuration();
SessionFactory sessionFactory = cfg.configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
//新增
Staff staff = new Staff();
staff.setName("Hibernate");
session.save(staff);
//獲取單個
Staff staff2 = (Staff) session.get(Staff.class, staff.getId());
if (staff2 != null)
System.out.println(staff2.getName());
//修改
staff2.setName("改后名字Hibernate2");
session.save(staff2);
//查詢 HQL
Query q = session.createQuery("from Staff");
List<Staff> list = q.list();
for (Staff staff3 : list) {
System.out.println(staff3.getName());
}
//刪除
// session.delete(staff2);
session.getTransaction().commit();
session.close();
sessionFactory.close();
}
}
上面是舉個例子楞陷,簡單的增刪改查。
寫這篇文章的目的不是教給大家Hibernate怎么用茉唉,而是說Hibernate學起來會很難固蛾,如果你有信心,有毅力度陆,完全可以一戰(zhàn)艾凯!