Hibernate学习02---Hibernate原理分析和模拟其实现


Hibernate实现原理

1、Configuration加载hibernate.cfg.xml

2、生成SessionFactory

3、加载对象关系映射文件*.hbm.xml

4、创建Session对象

5、调用Session API保存对象

6、根据Dialect生成和底层数据库平台相关的sql代码

7、对JDBC封装,执行sql脚本

从本质上讲,Hibernate还是最终还是通过JDBC进行数据库的访问,只是对JDBC进行了封装。

Hibernate实现的关键技术

1、DOM(解析XML文档)DOM/SAX------dom4j

2、反射机制

 

 

模拟Hibernate实现

新建java项目,把需要的jar导入(dom4j.jar,还有mysql驱动包)

1.pojo类Student.java

package com.demo.pojo;

public class Students {
	private int sid;
	private String sname;
	public int getSid() {
		return sid;
	}
	public void setSid(int sid) {
		this.sid = sid;
	}
	public String getSname() {
		return sname;
	}
	public void setSname(String sname) {
		this.sname = sname;
	}
	
}


2.对象关系映射文件 Student.hbm.xml

<?xml version="1.0"?>

<hibernate-mapping package="com.demo.pojo">
	<class name="Students" table="students">
		<property name="sid" column="sid" type="int" />
		<property name="sname" column="sname" type="string"  />
	</class>
</hibernate-mapping>

 

3.创建自己的Session类

这个类有三个属性(用来存放pojo中的属性与数据库字段对应的maps,存放表名的tableName,存放getter方法的methodNames)

有三个方法(构造方法,createSQL,Save)

构造方法对Students.hbm.xml进行解析,初始化maps,tableName还有methodName的大小

createSQL方法就是根据maps中的属性-字段来拼接sql字符串了

save方法利用反射和jdbc操作对数据进行操作

 

package com.demo.dao;

import java.io.File;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.demo.pojo.Students;


public class Session 
{
	//属性--字段 O-R mapping的映射关系
	private Map<String,String> maps = new HashMap<String, String>();
	//表名
	private String tableName;
	//保存实体类中的方法(只保存getter方法),后面会用反射得到方法的返回类型 ,从而在preparedStatement.setXXX方法中用
	private String[] methodNames;
	
	public Session()throws Exception
	{
		SAXReader reader = new SAXReader();//生成reader对象
		File f = new File("Students.hbm.xml");
		Document doc = (Document)reader.read(f);//生成文档对象
		Element root = doc.getRootElement();//获取根节点
		List list1 = (List) root.elements();
		for(int i=0;i<list1.size();i++)//遍历root下的子节点
		{
			Element node1 = (Element) list1.get(i);
			tableName = node1.attributeValue("table");//得到属性为table的值
			List list2 = node1.elements();//得到node1下的子节点
			for(int j=0;j<list2.size();j++)//遍历node1下的子节点
			{
				Element node2 = (Element)list2.get(j);
				maps.put(node2.attributeValue("name"), node2.attributeValue("column"));
			}
			methodNames = new String[maps.size()];//初始化methodNames的大小
		}
	}
	
	public void save(Students s) throws Exception
	{
		String sql = createSQL();
		System.out.println(sql);
		Connection conn = null;
		PreparedStatement pstate = null;
		Class.forName("com.mysql.jdbc.Driver");
		conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root","");
		pstate = conn.prepareStatement(sql);

		//遍历方法数组,利用反射得到方法的返回类型
		for(int i=0;i<methodNames.length;i++)
		{
			//利用反射,根据方法的字符串名字,得到一个方法对象
			Method m = s.getClass().getMethod(methodNames[i]);
			//利用反射,根据方法对象,得到方法的返回类型
			Class c = m.getReturnType();
			//如果返回类型是int
			if(c.getName().equals("java.lang.Integer")||c.getName().equals("int"))
			{
				int value = (Integer) m.invoke(s);
				pstate.setInt(i+1,value);//则设置int
			}
			//如果返回类型是String
			if(c.getName().equals("java.lang.String"))
			{
				String value = (String) m.invoke(s);
				pstate.setString(i+1,value);//则设置String
			}
		}
		
		pstate.executeUpdate();//最后执行
		pstate.close();//关闭连接
		conn.close();
		
	}
	
	//拼接sql语句
	private String createSQL()
	{
		int index=0;
		//问号的拼接字符串
		String qutoes="";
		//得到表的字段名,中间加逗号拼接起来
		String columns = "";
		for(String key:maps.keySet())
		{
			String value = maps.get(key);
			columns +=value+",";
			//同时把getXXX方法存入到数组中
			methodNames[index++]="get"+Character.toUpperCase(key.charAt(0))+key.substring(1);
		}
		for(int i=0;i<maps.size();i++)
		{
			qutoes +="? ,";
		}
		columns = columns.substring(0,columns.length()-1);
		qutoes = qutoes.substring(0, qutoes.length()-1);
		return "insert into "+tableName+" ("+columns+") values ("+qutoes+")";
	}
	
}


4、最后就是一个测试类了


 

package com.demo.dao;

import com.demo.pojo.Students;

public class Client {

	
	public static void main(String[] args)throws Exception {

		Session sessoin = new Session();
		Students student = new Students();
		student.setSid(1);
		student.setSname("wangwu");
		sessoin.save(student);
	}

}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值