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