第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

首頁 慕課教程 Hibernate 入門教程 Hibernate 入門教程 自定義類 Hibernate 框架的基本過程

自定義類 Hibernate 框架的基本過程

1. 前言

不要一味地迷信,要善于質(zhì)疑,善于打破。這應(yīng)該是我們?cè)趯W(xué)習(xí)框架時(shí)應(yīng)該保持的心態(tài)。

Hibernate 是所有 JDBC 框架中封裝最高的、使用起來最便利的框架之一。對(duì)于初學(xué)者而言,要么在感嘆它的神奇,要么敬畏它的存在。

但是,作為一個(gè)真正的開發(fā)者,應(yīng)該有破有立的想法。

本節(jié)課程試圖通過一個(gè)簡易的 JDBC 框架的實(shí)現(xiàn)流程描述,讓大家更清晰地了解 Hibernate 框架的設(shè)計(jì)過程。

TIps: 框架的編寫是一個(gè)比較復(fù)雜的過程,并不是一言兩語能說清楚的,本文中的代碼介于偽代碼和真實(shí)代碼之間 ,僅僅用來幫助大家理解 Hibernate 的框架基礎(chǔ)原理。

2. 讀取配置信息

簡易框架主要模擬 3 個(gè)組件,分別對(duì)應(yīng) Hibernate 中的 Configuration、SessionFactory、Session 組件。

Configuration 組件的作用:解析配置文件中的信息。

Tips: 簡易框架中,保持配置文件格式及內(nèi)容和 Hiberante 的主配置文件一致。

查看一下 Configuration 類的結(jié)構(gòu):

public class Configuration {
	//保存配置文件中的 property 元素信息
	private Map<String,String> pros;
	//保存配置文件中的映射類
	private List<String> mappings;
	
	public Configuration() {
		this.pros=new HashMap<String, String>();
		this.mappings=new ArrayList<String>();
	}
	
	/**
	 * 讀取配置文件
	 */
	public void configure() throws DocumentException {
		configure("/hibernate.cfg.xml");
	}

	private void configure(String resource) throws DocumentException {
		InputStream stream =Configuration.class.getResourceAsStream(resource);
		doConfigure( stream);
	}

	/**
	 * 使用 DOM4j XML 解析器解決配置文件中的信息
	 */
	private void doConfigure(InputStream stream) throws DocumentException {
		SAXReader saxReader=new SAXReader();
		Document doc= saxReader.read(stream);
		Element rootEle= doc.getRootElement();
		Element sfEle= rootEle.addElement("session-factory");		
		List<Element> propertys= sfEle.elements("property");
		for (Element ele : propertys) {
			this.pros.put(ele.attributeValue("name"), ele.getText());
		}
		List<Element> mappings= sfEle.elements("mapping");
		for (Element m : mappings) {
		    this.mappings.add(m.attributeValue("class"));
		}	
	}
    /**
    *創(chuàng)建會(huì)話工廠
    *
    */
	public SessionFactory buildSessionFactory()  {
		return new SessionFactory(this.pros,this.mappings);
	}
}

Hibernate 的主配置文件中有很多配置項(xiàng),因受限于文章篇幅和本文初設(shè)目標(biāo),這里只解析 2 類信息:

  • 數(shù)據(jù)庫連接信息;
  • 實(shí)體類路徑信息。

基礎(chǔ)好的學(xué)習(xí)者可以查閱 Hibernate 的源代碼。

3. 會(huì)話工廠

會(huì)話工廠的核心作用:建立和數(shù)據(jù)庫系統(tǒng)的連接,創(chuàng)建會(huì)話對(duì)象。

創(chuàng)建時(shí)需要依賴 Configuration 組件解析出來的信息。Hiberante 的會(huì)話工廠的源代碼實(shí)現(xiàn)比較復(fù)雜,代碼具有良好的結(jié)構(gòu)性,會(huì)衍生出很多輔助性組件。

因?yàn)橹皇钦f明問題,本文中的工廠僅僅用來創(chuàng)建會(huì)話對(duì)象,不考慮性能、緩存、事務(wù)等各方面問題,也不刻意講究代碼的結(jié)構(gòu)性。

簡易框架中的會(huì)話工廠的代碼簡單但具有說明力:

public class SessionFactory {
	private Map<String, String> pros;
	private List<String> mappings;
	private ThreadLocal<Session> threadLocal;
	public SessionFactory(Map<String, String> pros, List<String> mappings) {
		this.pros = pros;
		this.mappings = mappings;
		this.threadLocal = new ThreadLocal<Session>();
	}
	public Connection getConn() {
		String driverClass = this.pros.get("connection.driver_class");
		String url = this.pros.get("connection.url");
		String userName = this.pros.get("connection.username");
		String password = this.pros.get("connection.password");
		try {
			Class.forName(driverClass);
			return DriverManager.getConnection(url, userName, password);
		} catch (ClassNotFoundException | SQLException e) {
			e.printStackTrace();
		}
		return null;
	}
	public Session openSession() {
		return new Session(this.getConn(), this.mappings);
	}
	public Session getCurrentSession() {
		Session session = this.threadLocal.get();
		if (session == null) {
			session = this.openSession();
			this.threadLocal.set(session);
		}
		return session;
	}
}

會(huì)話工廠類中有 2 個(gè)創(chuàng)建 Session 的方法,一個(gè)是普通的創(chuàng)建方法,另一個(gè)是從線程上下文中檢查是否已經(jīng)存在 Session 對(duì)象。

4. 會(huì)話對(duì)象

Session 對(duì)象提供具體的方法用來對(duì)數(shù)據(jù)庫中的數(shù)據(jù)進(jìn)行相關(guān)操作。

public class Session<T> {
private Connection conn;
private List<String> mappings;

public Session(Connection conn, List<String> mappings) {
	this.conn=conn;
	this.mappings=mappings;
}

public T get(Class<T> clz,Serializable ser) {
	//構(gòu)建 SQL 		
	//得到結(jié)果集
	//封裝數(shù)據(jù)
	return null;
}

public Object load(Class<T> clz,Serializable ser) {
	return null;
}
public int save() {
	return 0;
}

//其它方法
}

在前面的《Hibernate 自動(dòng)生成 SQL 語句》和《 Hibernate 自動(dòng)進(jìn)行數(shù)據(jù)封裝 》章節(jié)中已經(jīng)講解了如何通過反射構(gòu)建 SQL 和數(shù)據(jù)封裝。請(qǐng)查閱相關(guān)內(nèi)容。

因?yàn)檠舆t加載是 Hibernate 中一個(gè)比較重要的特性,所以,這里講解一下 load 方法的實(shí)現(xiàn)原理。load()方法調(diào)用時(shí)并沒有直接訪問數(shù)據(jù)庫,而是返回給用戶一個(gè)代理對(duì)象,只有當(dāng)使用者調(diào)用代理對(duì)象的 getXXX()方法時(shí),才會(huì)進(jìn)入數(shù)據(jù)庫。

做到這一點(diǎn)并不難,使用代理設(shè)計(jì)模式便可。

代理設(shè)計(jì)模式中創(chuàng)建代理對(duì)象的方案有 2 種:

  • 靜態(tài)代理對(duì)象;
  • 動(dòng)態(tài)代理對(duì)象。

一般都會(huì)使用動(dòng)態(tài)方式創(chuàng)建代理對(duì)象,動(dòng)態(tài)代理對(duì)象的常用創(chuàng)建方案有 2 種:

  • 使用 JDK 中提供的 Proxy 類創(chuàng)建;
  • 第三方實(shí)現(xiàn),如 cglib 庫。

使用 Proxy 創(chuàng)建時(shí)有一個(gè)前提條件,需要被代理的對(duì)象提供接口規(guī)范,使用 cglib 就不需要,因是第三方實(shí)現(xiàn),則需要在項(xiàng)目中導(dǎo)入依賴包。

通過代理設(shè)計(jì)模式的回調(diào)機(jī)制,load()方法就能實(shí)現(xiàn)當(dāng)需要時(shí)再觸發(fā)對(duì)應(yīng)的數(shù)據(jù)庫操作。

5. 小結(jié)

本節(jié)課以簡易代碼的方式描述了 Configuration、SessionFactory、Session 3 個(gè)組件的功能實(shí)現(xiàn),以及其相互之間的依賴關(guān)系。

但并沒有更深入的接軌 Hibennate 的源代碼,Hiberanate 源代碼中有很多商業(yè)性的解決方案,值得大家深究參考。

希望通過本次課程,能讓大家更進(jìn)一步的認(rèn)識(shí) Hibernate 。