夜谭hibernate的运行原理

作为一款优秀封装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运行原理就跟大家探讨到这里,想交流的朋友请留言或私信。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值