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);
}
}