Hibernate学习_001_模拟hibernate的实现
来源:互联网 发布:网络flash英文歌曲 编辑:程序博客网 时间:2024/05/17 07:56
前言:本人菜鸟一只,原来一直认为拜读大神们神作来提升自己能力就已经足够,但是发现这样其实是对自己能力提升设置了一个壁垒,所以现在我会把自己的学习成果写成博文,这样,既方便大家学习交流,也便于同行发现自己学习认知上的不足并给与指正。同时,我也认为,技术博客不仅仅是一个分享知识的平台,同时也是自己总结所学知识的一个平台,不管是原创,还是参考其他大牛们神作后的所思所想,只要是自己经过思考所得,那就有它存在的价值。
以前,用ssh做过几个小的项目,但是仅仅是机械式的操作,局限于使用,并没有对其内部实现机制进行深入的理解,考完研,闲来无事,决定重新彻头彻尾学一遍ssh,个人觉得其实struts+hibernate+spring架构中,struts最为简单,无非就是action,拦截器等的各种配置,spring最为复杂,因为其对于各个组件,框架的支持,十分的繁杂,比如,java securty, Restful等。 而hibernate则介于两者之间。
今天参考hibernate的文档实现了ssh的集成化,决定写一个hibernate的模拟实现。 我们大家其实都会使用hibernate,无非就是CRUD.OOA,OOD,这些东西,感觉十分简单,可是我们也许从没有想过为什么会有hibernate.cfg.xml,Entity.hbm.xml文件,也很少去想通过session去save一个对象的时候,hibernate内部究竟帮我做了什么,为什么一个标准的Java Bean 属性一定会有getXxx()方法。这些我通过以下一个例子对大家说明。(如果说的不对,欢迎大家指正,相互学习。)
首先,我们建立好自己的实体类。(这个类就是一个标准的Java Bean ,无需多解释。)
public class Person{private int id;private String name;private int age;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}}
然后,建立好我们的Session类。(这个类就是模拟Hibernate中的session的。)
注:以下代码我们假设我们从配置文件已经读出数据库表名,从实体映射中已经读出来属性名和字段名的对应关系。
public class Session {//待处理sql语句。String sql ="";//数据库表名String tableName="Person";//此Map对象模拟的是从*.hbm.xml或者是从@Entity中读出来的(数据库列名:属性)键值对。Map<String,String> vfs;//取得对应Entity类中的getProperty方法。String[] methodNames;public Session(){vfs = new HashMap<String,String>();vfs.put("id", "id");vfs.put("name", "name");vfs.put("age", "age");//按照vfs的长度来设置方法名数组的长度。methodNames = new String[vfs.size()];}public void save(Person s) throws Exception{Class.forName("com.mysql.jdbc.Driver");Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/HibernateDemo", "root", "root");//拼凑sql语句。而且顺便在这个方法中把sql中用到的属性放到methodNames中,以便通过反射形式给SQL赋值的时候使用。createSQL();PreparedStatement pstm = conn.prepareStatement(sql);//在以下循环中对sql语句中的占位符“?”进行赋值。for(int index = 0 ; index < vfs.size();index ++ ){String value = methodNames[index];String property = Character.toUpperCase(value.charAt(0))+value.substring(1);String method = "get"+property;//以下则是通过反射来模拟hibernate核心实现机制。 Method m = s.getClass().getMethod(method);if(m.getReturnType().getName().equals("java.lang.String")){pstm.setString(index+1, (String)m.invoke(s));}if(m.getReturnType().getName().equals("int")){pstm.setInt(index+1, (Integer)m.invoke(s));}}pstm.executeUpdate();pstm.close();conn.close();}private void createSQL() {//填充(?,?,?)形式的字符串String place1 = "";for(int i = 0 ; i < vfs.size(); i ++){place1 += "?,";}place1 = place1.substring(0, place1.length()-1);//填充(id,name,age)形式字符串。String values = "";int methodIndex = 0 ; for(String m : vfs.keySet()){values += m +",";//把属性设置到对应的数组中,到时候通过反射赋值的时候使用。methodNames[methodIndex++]= vfs.get(m);}values = values.substring(0,values.length()-1);sql = "insert into "+tableName +" ("+values+") values ("+place1+")";}}接着就是我们的测试代码:
public class PersonTest {public static void main(String[] args) throws Exception{ Session session = new Session(); Person p = new Person(); p.setId(2); p.setName("s"); p.setAge(1); session.save(p);}}
其实,hibernate底层是采用的还是jdbc来操作数据库,我们在使用hibernate的session保存一个对象的时候,其实是会调用所保存对象的getXxx()方法,在底层jdbc中对参数进行赋值,所以,按常理来说,我们所保存的java对象,一般最好是一个标准的Java Bean。还有一点,其实hibernate内部实现机制并没有大量的采用反射机制,可能是效率的影响吧,更多的hibernate实现是通过直接生成二进制码的方式来实现,这样效率得到很大提升。
理解如有误区,欢迎大家指点,相互交流,共同进步。
- Hibernate学习_001_模拟hibernate的实现
- Hibernate:模拟Hibernate实现
- Hibernate学习02---Hibernate原理分析和模拟其实现
- 简单模拟实现hibernate
- hibernate实现原理模拟
- 简易模拟Hibernate实现
- hibernate模拟实现insert
- Hibernate模拟实现
- hibernate模拟实现
- 模拟Hibernate实现
- 模拟hibernate实现的JAVA源码
- 简单模拟hibernate的实现原理
- 模拟hibernate save方法的实现过程
- Hibernate学习笔记之Hibernate原理分析及模拟Hibernate实现
- 使用反射模拟实现hibernate
- Hibernate学习07---Hibernate的Session-API实现CRUD
- Hibernate的简介和Hinbernate的简单模拟实现
- Hibernate的出现和Hinbernate的简单模拟实现
- ibatis和hibernate的区别
- 服务器中判断客户端socket断开连接的方法
- android4.4 Keyguard 锁屏之----布局篇
- 使用 Broadcast Receiver 接收广播消息
- 关于ListView中adapter调用notifyDataSetChanged无效的原因
- Hibernate学习_001_模拟hibernate的实现
- 那么相似,可还不是-------Day84
- [水]ZOJ1205
- Linux中硬链接和软链接的区别和联系
- bzoj1669 [Usaco2006 Oct]Hungry Cows饥饿的奶牛
- Fermat’s Chirstmas Theorem(素数筛)
- 自己写的atoi函数
- 剪贴板应用
- 未能找到类型或命名空间名称"xxxxxx"的真正原因