Hibernate学习_001_模拟hibernate的实现

前言:本人菜鸟一只,原来一直认为拜读大神们神作来提升自己能力就已经足够,但是发现这样其实是对自己能力提升设置了一个壁垒,所以现在我会把自己的学习成果写成博文,这样,既方便大家学习交流,也便于同行发现自己学习认知上的不足并给与指正。同时,我也认为,技术博客不仅仅是一个分享知识的平台,同时也是自己总结所学知识的一个平台,不管是原创,还是参考其他大牛们神作后的所思所想,只要是自己经过思考所得,那就有它存在的价值。

        以前,用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实现是通过直接生成二进制码的方式来实现,这样效率得到很大提升。

       理解如有误区,欢迎大家指点,相互交流,共同进步。

       

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值