作爲一款優秀封裝dao層的框架,被衆多同仁使用,這篇文章再爲學習hibernate的朋友提供一個理解原理的參考。
下面是我模擬hibernate的運行原理寫的一個程序,希望對大家有用!
首先跟大家分享框架結構圖
第一步,創建Execute對象
第二步,創建ConfigManager對象
第三步,創建configFile對象,configFile包含數據庫連接部分和實體類映射文件
第四步,讀取數據庫連接映射文件盒實體類配置文件
第五步,調用Execute對象的get方法
第六步,根據實體映射類構造SQL語句
第七步,設置對象屬性,返回實體對象
看完結構圖,由我帶大家瀏覽一下設計流程:
1、首先創建一個Web Project
2、然後需要導入一個解析XML文件的jar包dom4j-1.6.1.jar和java訪問oracle數據庫的jar包classes12.jar
3、需要在src下寫一個名叫Config.dtd文件和Mapping.dtd,這個文件用於規範配置文件
a、Config.dtd
<!ELEMENT hibernate (session-factory)>
<!ELEMENT session-factory (property*,mapping*)>
<!ELEMENT property (#PCDATA)>
<!ATTLIST property
name CDATA #REQUIRED>
<!ELEMENT mapping EMPTY>
<!ATTLIST mapping
resource CDATA #REQUIRED>
b、Mapping.dtd
<!ELEMENT hibernate-mapping (class)>
<!ELEMENT class (id,property*)>
<!ATTLIST class
name CDATA #REQUIRED
table CDATA #REQUIRED>
<!ELEMENT id EMPTY>
<!ATTLIST id
name CDATA #REQUIRED
type CDATA "java.lang.String"
column CDATA #REQUIRED>
<!ELEMENT property EMPTY>
<!ATTLIST property
name CDATA #REQUIRED
type CDATA "java.lang.String"
column CDATA #REQUIRED>
4、下面就開始寫各個類
a、實體映射文件MappingFile類和映射屬性Attribute類
package com.huan.frame;
import java.util.*;
public class MappingFile {
private String name;
private String className;
private String tableName;
private String primary;
private List<Attribute> attlist = new ArrayList<Attribute>();
public void addAttribute(Attribute att){
attlist.add(att);
}
public List<Attribute> getAttlist() {
return attlist;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getTableName() {
return tableName;
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
public String getPrimary() {
return primary;
}
public void setPrimary(String primary) {
this.primary = primary;
}
}
package com.huan.frame;
public class Attribute {
private String name;
private String type;
private String column;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getColumn() {
return column;
}
public void setColumn(String column) {
this.column = column;
}
}
b、實例化MappingManager類
package com.huan.frame;
public class MappingManager {
public static Object createInstance(MappingFile file){
try {
return Class.forName(file.getName()).newInstance();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
c、配置文件ConfigFile類
package com.huan.frame;
import java.util.*;
public class ConfigFile {
private String connectionDriver;
private String connectionURL;
private String connectionUser;
private String connectionPassword;
private Map<String,MappingFile> mappings = new HashMap<String,MappingFile>();
public void addMapping(MappingFile mf){
mappings.put(mf.getName(), mf);
}
public MappingFile getMapping(String name){
return mappings.get(name);
}
public String getConnectionDriver() {
return connectionDriver;
}
public void setConnectionDriver(String connectionDriver) {
this.connectionDriver = connectionDriver;
}
public String getConnectionURL() {
return connectionURL;
}
public void setConnectionURL(String connectionURL) {
this.connectionURL = connectionURL;
}
public String getConnectionUser() {
return connectionUser;
}
public void setConnectionUser(String connectionUser) {
this.connectionUser = connectionUser;
}
public String getConnectionPassword() {
return connectionPassword;
}
public void setConnectionPassword(String connectionPassword) {
this.connectionPassword = connectionPassword;
}
}
d、配置管理ConfigManager類
package com.huan.frame;
import java.io.InputStream;
import java.sql.*;
import java.util.*;
import org.dom4j.*;
import org.dom4j.io.SAXReader;
public class ConfigManager {
private ConfigFile config;
public ConfigManager(){
config = new ConfigFile();
readConfig();
}
public void readConfig(){
try {
InputStream is = getClass().getResourceAsStream("/Config.xml");
if(is == null) throw new Exception("hibernate:配置文件未找到!");
Document doc = new SAXReader().read(is);
Element root = doc.getRootElement();
Iterator<Element> sessionNode = root.elementIterator("session-factory");
Element child = sessionNode.next();
Iterator<Element> propertys = child.elementIterator("property");
Element node = null;
while(propertys.hasNext()){
node = propertys.next();
if(node.attributeValue("name").trim().equals("connection.driver"))
config.setConnectionDriver(node.getTextTrim());
if(node.attributeValue("name").trim().equals("connection.uri"))
config.setConnectionURL(node.getTextTrim());
if(node.attributeValue("name").trim().equals("connection.user"))
config.setConnectionUser(node.getTextTrim());
if(node.attributeValue("name").trim().equals("connection.password"))
config.setConnectionPassword(node.getTextTrim());
}
Iterator<Element> mappings = child.elementIterator("mapping");
while(mappings.hasNext()){
node = mappings.next();
MappingFile mf = readMapping(node.attributeValue("resource"));
config.addMapping(mf);
}
System.out.println("hibernate:配置文件加載完畢!");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public MappingFile readMapping(String path){
MappingFile mapping = new MappingFile();
try {
if(path == null) throw new Exception("hibernate:映射文件未找到!");
mapping.setName(path.substring(5,path.lastIndexOf(".")).replaceAll("/", "."));
System.out.println("hibernate:映射文件名:" + mapping.getName());
path = path.substring(4);
System.out.println("hibernate:映射路徑名:" + path);
Properties properties = new Properties();
InputStream is = getClass().getResourceAsStream(path);
if(is == null) throw new Exception("hibernate:映射文件加載失敗!");
Document doc = new SAXReader().read(is);
Element root = doc.getRootElement();
Iterator<Element> sessionNode = root.elementIterator("class");
Element child = sessionNode.next();
mapping.setClassName(child.attributeValue("name"));
mapping.setTableName(child.attributeValue("table"));
Iterator<Element> ids = child.elementIterator("id");
Element id = ids.next();
mapping.setPrimary(id.attributeValue("name"));
Attribute attId = new Attribute();
attId.setName(id.attributeValue("name"));
attId.setType(id.attributeValue("type"));
attId.setColumn(id.attributeValue("column"));
mapping.addAttribute(attId);
Iterator<Element> propertys = child.elementIterator("property");
Element property = null;
Attribute att = null;
System.out.println("hibernate:進入屬性加載循環!");
while(propertys.hasNext()){
property = propertys.next();
att = new Attribute();
att.setName(property.attributeValue("name"));
att.setType(property.attributeValue("type"));
att.setColumn(property.attributeValue("column"));
mapping.addAttribute(att);
}
System.out.println("hibernate:映射文件加載完畢!");
return mapping;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public MappingFile getMapping(String name){
return config.getMapping(name);
}
public Connection openConnection(){
Connection conn = null;
try {
Class.forName(config.getConnectionDriver());
conn = DriverManager.getConnection(config.getConnectionURL()
,config.getConnectionUser(),config.getConnectionPassword());
return conn;
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public void closeAll(Connection conn,PreparedStatement pstmt,ResultSet rs){
try {
if(rs != null) rs.close();
if(pstmt != null) pstmt.close();
if(conn != null) conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
e、執行Execute類
package com.huan.frame;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.List;
public class Execute {
private ConfigManager manager = new ConfigManager();
public Object get(Class c,int id){
String[] str = c.toString().split(" ");
MappingFile mf = manager.getMapping(str[1]);
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
Class clazz = Class.forName(mf.getName());
Object obj = MappingManager.createInstance(mf);
if(obj == null) throw new Exception("hibernate:反射生成對象實例化失敗!");
conn = manager.openConnection();
if(conn == null) throw new Exception("hibernate:連接數據庫失敗!");
String sql = buildSql(mf);
System.out.println("hibernate:" + sql);
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, id);
rs = pstmt.executeQuery();
int size = mf.getAttlist().size();
String methodName = null;
String type = null;
Method[] methods = clazz.getDeclaredMethods();
while(rs.next()){
System.out.println("hibernate:讀取數據...");
for(int i = 0; i < size; i++){
methodName = buildMethodName(mf.getAttlist().get(i).getName());
System.out.println("hibernate:方法名:" + methodName);
for (Method method : methods) {
System.out.println("hibernate:遍歷方法名..." + method.getName());
if(methodName.equals(method.getName())){
type = mf.getAttlist().get(i).getType();
System.out.println("hibernate:參數類型:" + type);
if(type.equals("java.lang.Integer")){
System.out.println("hibernate:" + method.getName() + "賦值");
method.invoke(obj, rs.getInt(i + 1));
break;
}
if(type.equals("java.lang.String")){
System.out.println("hibernate:" + method.getName() + "賦值");
method.invoke(obj, rs.getString(i + 1));
break;
}
}
}
}
}
return obj;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
manager.closeAll(conn, pstmt, rs);
}
return null;
}
public String buildSql(MappingFile file){
try {
if(file == null) throw new Exception("創建SQL語句的MF文件爲空!");
String sql = "SELECT ";
List<Attribute> attList = file.getAttlist();
for(int i = 0; i < attList.size(); i++){
if(i == 0) sql += attList.get(i).getColumn();
else sql += "," + attList.get(i).getColumn();
}
return sql += " FROM " + file.getTableName() + " WHERE " + file.getPrimary() + " = ?";
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public String buildMethodName(String attName){
try {
if(attName == null || attName.isEmpty()) throw new Exception("創建方法的屬性名爲空!");
return "set" + attName.substring(0,1).toUpperCase() + attName.substring(1);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
5、寫完各個類之後就是打包,右鍵點擊項目export,保存爲JAR file文件即可!
瀏覽完設計流程,就讓我們測試一下我們的hibernate框架吧,let's go!
1、創建一個Web Project項目,導入咱們剛剛寫好的包,還要導入dom4j-1.6.1.jar和classes12.jar,別忘了!
2、創建配置文件和實體類和實體映射文件,注意實體類和實體映射文件必須在一個包下
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ActionConfig[
<!ELEMENT hibernate (session-factory)>
<!ELEMENT session-factory (property*,mapping*)>
<!ELEMENT property (#PCDATA)>
<!ATTLIST property
name CDATA #REQUIRED>
<!ELEMENT mapping EMPTY>
<!ATTLIST mapping
resource CDATA #REQUIRED>
]>
<hibernate>
<session-factory>
<property name="connection.driver">oracle.jdbc.driver.OracleDriver</property>
<property name="connection.uri">jdbc:oracle:thin:@localhost:1521:orcl</property>
<property name="connection.user">huan</property>
<property name="connection.password">orcl</property>
<mapping resource="/src/com/huan/entity/User.xml"/>
</session-factory>
</hibernate>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ActionConfig[
<!ELEMENT hibernate-mapping (class)>
<!ELEMENT class (id,property*)>
<!ATTLIST class
name CDATA #REQUIRED
table CDATA #REQUIRED>
<!ELEMENT id EMPTY>
<!ATTLIST id
name CDATA #REQUIRED
type CDATA "java.lang.String"
column CDATA #REQUIRED>
<!ELEMENT property EMPTY>
<!ATTLIST property
name CDATA #REQUIRED
type CDATA "java.lang.String"
column CDATA #REQUIRED>
]>
<hibernate-mapping>
<class name="com.huan.entity.User" table="users">
<id name="id" type="java.lang.Integer" column="id"/>
<property name="name" column="name"/>
<property name="pwd" column="password"/>
</class>
</hibernate-mapping>
3、創建執行類Execute對象,調用get方法。之前我寫了一個struts模擬用的是虛擬數據庫,這次我將我的模擬hibernate替換掉虛擬數據庫
package com.huan.test;
import java.util.*;
import com.huan.entity.User;
import com.huan.frame.Execute;
public class UserDaoImp {
private Execute execute = null;
public User getUserById(int id){
execute = HibnateUtil.getExecute();
return (User)execute.get(User.class, id);
}
}
還是老規則,輸入數據庫裏有的用戶資料進入index.jsp就算成功了!
今天的hibernate運行原理就跟大家探討到這裏,想交流的朋友請留言或私信。