菜鸟学SSH(十五)——简单模拟Hibernate实现原理
之前寫(xiě)了Spring的實(shí)現(xiàn)原理,今天我們接著聊聊Hibernate的實(shí)現(xiàn)原理,這篇文章只是簡(jiǎn)單的模擬一下Hibernate的原理,主要是模擬了一下Hibernate的Session類(lèi)。好了,廢話不多說(shuō),先看看我們的代碼:
package com.tgb.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;import org.jdom.Document; import org.jdom.Element; import org.jdom.input.SAXBuilder; import org.jdom.xpath.XPath;import com.tgb.hibernate.model.User;public class Session {//表名String tableName = "user"; //存放數(shù)據(jù)庫(kù)連接配置private Map<String, String> conConfig = new HashMap<String, String>();//存放實(shí)體屬性private Map<String ,String > columns = new HashMap<String ,String >(); //實(shí)體的get方法集合 String methodNames[]; public Session () { //初始化實(shí)體,這里就不用讀取配置文件的方式了,有點(diǎn)麻煩。 columns.put("id", "id"); columns.put("name", "name"); columns.put("password", "password"); methodNames = new String[columns.size()]; } /*** 創(chuàng)建數(shù)據(jù)庫(kù)連接* @return* @throws Exception*/public Connection createConnection() throws Exception {//解析xml文件,讀取數(shù)據(jù)庫(kù)連接配置 SAXBuilder sb = new SAXBuilder(); Document doc = sb.build(this.getClass().getClassLoader().getResourceAsStream("hibernate.cfg.xml")); Element root = doc.getRootElement(); List list = XPath.selectNodes(root, "/hibernate-configuration/property"); for (int i = 0; i < list.size(); i++) { Element property = (Element) list.get(i); String name = property.getAttributeValue("name"); String value = property.getText(); conConfig.put(name, value); } //根據(jù)配置文件獲得數(shù)據(jù)庫(kù)連接Class.forName(conConfig.get("driver")); Connection con = DriverManager.getConnection(conConfig.get("url"),conConfig.get("username"),conConfig.get("password")); return con;}/*** save方法,持久化對(duì)象* @param user*/public void save(User user) { String sql = createSql(); System.out.println(sql); try { Connection con = createConnection(); PreparedStatement state = (PreparedStatement) con.prepareStatement(sql); for(int i=0;i<methodNames.length;i++) { //得到每一個(gè)方法的對(duì)象 Method method = user.getClass().getMethod(methodNames[i]); //得到他的返回類(lèi)型 Class cla = method.getReturnType(); //根據(jù)返回類(lèi)型來(lái)設(shè)置插入數(shù)據(jù)庫(kù)中的每個(gè)屬性值。 if(cla.getName().equals("java.lang.String")) { String returnValue = (String)method.invoke(user); state.setString(i+1, returnValue); } else if(cla.getName().equals("int")) { Integer returnValue = (Integer) method.invoke(user); 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(); } } /** * 得到sql語(yǔ)句 * @return 返回sql語(yǔ)句 */ private String createSql() { //strColumn代表數(shù)據(jù)庫(kù)中表中的屬性列。并將其連接起來(lái)。 String strColumn = ""; int index=0; for(String key :columns.keySet()) { strColumn +=key+","; String v = columns.get(key); //獲得屬性的get方法,需要將屬性第一個(gè)字母大寫(xiě)如:getId()v = "get" + Character.toUpperCase(v.charAt(0)) + v.substring(1); methodNames[index] = v; index++; } strColumn = strColumn.substring(0, strColumn.length()-1); //拼接參數(shù)占位符,即:(?, ?, ?)String strValue = ""; for(int i=0;i<columns.size();i++) strValue +="?,"; strValue = strValue.substring(0,strValue.length()-1); String sql = "insert into " + tableName +"(" + strColumn + ")" + " values (" + strValue + ")"; return sql; } }?
以上代碼主要是完成了Hibernate的save()方法,該類(lèi)有一個(gè)構(gòu)造方法,一個(gè)構(gòu)建sql語(yǔ)句的方法,一個(gè)獲得數(shù)據(jù)庫(kù)連接的方法。最后通過(guò)save()方法結(jié)合前面幾個(gè)方法獲得結(jié)果,將實(shí)體對(duì)象持久化到數(shù)據(jù)庫(kù)。
基本原理就是:首先,獲得數(shù)據(jù)庫(kù)連接的基本信息;然后,獲得實(shí)體的映射信息;接著,也是最關(guān)鍵的步驟,根據(jù)前面獲得的信息,組裝出各種sql語(yǔ)句(本例只有簡(jiǎn)單的insert),將實(shí)體按照不同的要求查找或更新(增、刪、改)到數(shù)據(jù)庫(kù)。
當(dāng)然Hibernate的具體實(shí)現(xiàn)遠(yuǎn)沒(méi)有這么簡(jiǎn)單,Hibernate中大量運(yùn)用了cglib的動(dòng)態(tài)代理,其中l(wèi)oad()方法就是一個(gè)例子。大家都知道,調(diào)用load()方法是Hibernate不會(huì)向數(shù)據(jù)庫(kù)發(fā)sql語(yǔ)句,load()方法得到的是目標(biāo)實(shí)體的一個(gè)代理類(lèi),等到真正用到實(shí)體對(duì)象的時(shí)候才會(huì)去數(shù)據(jù)庫(kù)查詢(xún)。這也是Hibernate的一種懶加載的實(shí)現(xiàn)方式。
總結(jié)一句話,這些框架之所以能夠做到靈活,就是因?yàn)樗鼈兌己芎玫睦昧藨屑虞d機(jī)制,在運(yùn)行期在確定實(shí)例化誰(shuí),需要誰(shuí)實(shí)例化誰(shuí),什么時(shí)候需要,什么時(shí)候?qū)嵗_@樣設(shè)計(jì)出來(lái)能不靈活嗎?這些思想值得我們好好研究,并運(yùn)用到我們的設(shè)計(jì)中去。
總結(jié)
以上是生活随笔為你收集整理的菜鸟学SSH(十五)——简单模拟Hibernate实现原理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: C#和.NET Framework的关系
- 下一篇: vlc框架流程解析(转)