hibernate作為orm模型的實(shí)現(xiàn)的1種,是java的對(duì)象模型和關(guān)系模型之間的橋梁,主要通過jdbc
的封裝來到達(dá)操作數(shù)據(jù)庫的目的,提供了1套相對(duì)全面的自動(dòng)化的api。簡單摹擬1下hibernate的
運(yùn)行原理,其實(shí)主要還是jdbc的使用,還是直接看看這個(gè)小例子
package com.tgb.cfl.hibernate;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 摹擬hibernatesession接口
* @author 陳方林
*
*
*/
public class Session {
//寄存實(shí)體屬性
private Map<String ,String > columns = new HashMap<String ,String >();
//字符串?dāng)?shù)組寄存實(shí)體的get方法集合
String methodNames[];
//初始化實(shí)體類屬性和方法集合
public Session () {
//初始化實(shí)體,這里就不用讀取配置文件的方式了,有點(diǎn)麻煩。
columns.put("name", "name");
columns.put("age", "age");
methodNames = new String[columns.size()];
}
/**
* save方法,持久化對(duì)象
* @param user
*/
public void save(Person person) {
//strColumn代表
數(shù)據(jù)庫中表中的屬性列。并將其連接起來。
String strColumn = "";
int index=0;
for(String key :columns.keySet())
{
strColumn +=key+",";
String v = columns.get(key);
//取得屬性的get方法
v = "get" + Character.toUpperCase(v.charAt(0)) + v.substring(1);
methodNames[index] = v;
index++;
}
strColumn = strColumn.substring(0, strColumn.length()⑴);
//拼接參數(shù)占位符,即:(?, ?)
String strValue = "";
for(int i=0;i<columns.size();i++)
strValue +="?,";
//獲得字符串子串
strValue = strValue.substring(0,strValue.length()⑴);
String sql = "insert into " + "Person" +"(" + strColumn + ")" + " values (" + strValue + ")";
System.out.println(sql);
try {
//獲得連接
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://localhost/test" ,"root", "123456");
//jdbcstate對(duì)象
PreparedStatement state = (PreparedStatement) con.prepareStatement(sql);
for(int i=0;i<methodNames.length;i++) {
//利用反射得到每個(gè)方法的對(duì)象
Method method = person.getClass().getMethod(methodNames[i]);
//得到他的返回類型
Class cla = method.getReturnType();
//根據(jù)返回類型來設(shè)置插入
數(shù)據(jù)庫中的每一個(gè)屬性值。
if(cla.getName().equals("java.lang.String")) {
String returnValue = (String)method.invoke(person);
state.setString(i+1, returnValue);
}
else if(cla.getName().equals("int")) {
Integer returnValue = (Integer) method.invoke(person);
state.setInt(i+1, returnValue);
}
}
//履行更新
state.executeUpdate();
state.close();
con.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Person p = new Person();
p.setAge("1");
p.setName("s2");
Session session = new Session();
try {
session.save(p);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
這個(gè)例子主要還是摹擬session接口中對(duì)實(shí)體類的操作,主要分為這樣幾個(gè)步驟
1.動(dòng)態(tài)拼接sql語句
2.根據(jù)反射得到實(shí)體類屬性的操作方法get***
3.得到數(shù)據(jù)庫連接
4.通過PreparedStatement對(duì)象來更新數(shù)據(jù)
這個(gè)是jdbc的對(duì)象,步驟主要又分為
a)從connection中獲得PreparedStatement對(duì)象
b)利用PreparedStatement對(duì)象配合get方法得到屬性值
5.垃圾回收(回收連接,對(duì)象關(guān)閉)
我們通過這個(gè)例子再回頭看看hibernate,hibernate給我們做了甚么?
第1步:動(dòng)態(tài)拼接sql語句是怎樣實(shí)現(xiàn)的呢?hibernate中有這樣1個(gè)配置文件叫***.hbm.xml,用來配置實(shí)體和數(shù)據(jù)庫之間的關(guān)系。這個(gè)也是hibernate約定好的,你這樣寫了,最后就會(huì)讀取這樣后綴名的文件這個(gè)是第1步。
第2步:利用反射得到對(duì)應(yīng)的get方法這個(gè)是利用反射來做到的主要還是通過jdk內(nèi)部的這個(gè)
java.util.reflect.method這個(gè)類來做的。也是在jdk的api基礎(chǔ)上做的。
第3步:得到數(shù)據(jù)庫連接。hibernate中有這樣1個(gè)配置文件叫做hibernate.properties配置文件,內(nèi)部配置了數(shù)據(jù)庫連接方言,數(shù)據(jù)庫驅(qū)動(dòng),數(shù)據(jù)庫地址,用戶名密碼等等。
例如:
也是hibernate這樣來約定的,好了你程序中在指定文件夾有這個(gè)文件,我直接讀取節(jié)點(diǎn)的數(shù)據(jù)便可。只不過上面的例子是在代碼里面寫死了。
第4步:這個(gè)是jdbc的preparedstatement對(duì)象的api
第5步:對(duì)應(yīng)的是jdk的api。
標(biāo)準(zhǔn)的hibernate步驟以下:
1.通過Configuration().configure();讀取并解析hibernate.cfg.xml配置文件
2.讀取hibernate.cfg.xml//讀取并解析映照信息
3.通過config.buildSessionFactory();//創(chuàng)建SessionFactory
4.sessionFactory.openSession();//打開Sesssion
5.session.beginTransaction();//創(chuàng)建事務(wù)Transation
6.persistent operate持久化操作
7.session.getTransaction().commit();//提交事務(wù)
8.關(guān)閉Session、SesstionFactory
再通過這張圖,我們發(fā)現(xiàn)其實(shí)hibernate也就是在JDBC上面多加了1層。讓我想起之前哪里聽到1句話,靈活配置
是甚么?不過就是加1層,頗具喜感,后來1想?yún)s又幾分道理。

所以回頭看看,其實(shí)從大體上,hibernate也只是在jdbc的封裝,簡化我們直接操作jdbc
的進(jìn)程。在java這里,jdbc還是最為原始的最為直接的方式,不能說這個(gè)方法不好,由于當(dāng)下
流行ibatis也是針對(duì)實(shí)體來創(chuàng)建不同的sql語句來做的,所以直接原始的方法也是有它的好處
的,比如:靈活、效力高。換過來,hibernate在jdbc的基礎(chǔ)之上的封裝,也避免了程序猿們
來直接去書寫繁瑣的sql語句和事務(wù)保護(hù)和緩存控制,另外開源也是1個(gè)方面。
固然這里對(duì)hibernate原理的講授只是hibernate的冰山1角。后面,例如hibernate的緩存、3態(tài)、和對(duì)實(shí)體關(guān)聯(lián)的處理、事務(wù)都是需要好好研究的。