这篇文章 可作为北京尚学堂 hibernate的学习笔记

再学习hibernate之前 得有一点反射的基础知识

package com.bjsxt.hibernate;

public class Stu {
	public int id;
	private String name;
	private int age;
       //省略get.set方法
}
package com.bjsxt.hibernate;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class MyHibernate {
	public static void main2(String[] args) {
		Stu stu=new Stu();
		stu.setAge(15);
		stu.setId(111);
		stu.setName("DDD");

		MySession session=new MySession();
		session.save(stu);
	}
}

如上所示 其实最复杂的就是MySession里面的save方法(其实会写save 别的delete update也是一样的)

ok 咱们一步一步来 既然要和数据库打交道 最少得两个部分吧 1和数据连接   2写sql

/* 获取数据库连接的函数*/
	public  Connection getConnection() {
		Connection con = null;	//创建用于连接数据库的Connection对象
		try {
			Class.forName("com.mysql.jdbc.Driver");// 加载Mysql数据驱动
			con = DriverManager.getConnection(
					"jdbc:mysql://localhost:3306/webexample?" +
							"useUnicode=true&characterEncoding=UTF-8",
					"root","");// 创建数据连接
		} catch (Exception e) {
			System.out.println("数据库连接失败" + e.getMessage());
		}
		return con;	//返回所建立的数据库连接
	}

第二部分组成sql就有点复杂了

insert into table (id,name,age) values(?,?,?)

最后的结果应该是这样对吧

我们已经知道实体类里面的各个属性 假定他与数据库中的各个字段名 对应(当然我们并不强调 两者必须相等 但最好相等)

既然一个是实体属性 一个是字段名 那么最好的结果就是hashmap喽

public class MySession {
	private Map<String, String> map;
	private String tableName="stu";

	public MySession() {
		map = new HashMap<String, String>();
		map.put("id", "id");          // key为实体类里面的属性名
		map.put("name", "name");      // value为对应表里面的字段名字
		map.put("age", "age");
	}
}

至于map的填充   在真正的hibernate中可以同xml也可以基于annotation 在这里不是重点 我们就直接给他默认

下面就是生成sql部分

注释掉的部分先不要看!!

public String creatSQL() {
		String sql;
		String str1 = new String();
		int index = 0;
		for (String key : map.keySet()) {
			str1 += key + ",";
		//	String v = map.get(key);
			// 下面是得到对应的bean中的get方法。也就是得到User类中的getId()、getUsername()、getPwd()方法。
			// 注意每个属性的get后面的第一个字母是大写,需要转换。
		//	v = "get" + Character.toUpperCase(v.charAt(0)) + v.substring(1);
		//	methodNames[index] = v; // 将方法保存在数组中。
		//	index++;
		}
                str1=str1.substring(0,str1.length()-1);//如果不加这一行会有什么后果 大家试试

		String str2=new String();
		for (int i = 0; i < map.size(); i++)
			str2+="?,";
		str2=str2.substring(0, str2.length()-1);
		sql="insert into "+tableName +" ("+str1+ ") "+"values ("+str2+")";
		return sql;

	}

生成的sql是带?的 也就是我们要用preparedstatement

那么我们如何填充问号

答案是 借助反射调用类里面的get方法

ok 再看看creatsql里面的注释掉的内容 应该没有疑问了吧

再下面请大家回家jdbc连数据库的基本内容

public void save(Object obj) {
		String sql = creatSQL();
		System.out.println(sql);

		Connection con = getConnection();	//创建用于连接数据库的Connection对象
		try {
			PreparedStatement st=(PreparedStatement) con.prepareStatement(sql);
			Method method=null;
			for (int j = 0; j < map.size(); j++) {
				method= obj.getClass().getMethod(methodNames[j]);
				Class<?> type=method.getReturnType();
				if (type.getName().equals("java.lang.String")) {
					String param=(String) method.invoke(obj);
					st.setString(j+1, param);                 //为什么要加一 大家自己看看
				}
				if (type.getName().equals("int")) {
					int param=(int) method.invoke(obj);
					st.setInt(j+1, param);
				}
				System.out.println(method.getName() + "--" + method.getReturnType());
			}
			st.execute();
			st.close();
			con.close();
		}catch (Exception e) {
		    // TODO: handle exception
			e.printStackTrace();
		}

	}

再看看一个完整的MySession

package com.bjsxt.hibernate;

import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import com.mysql.jdbc.PreparedStatement;

public class MySession {
	private Map<String, String> map;
	private String tableName="stu";
	private String[] methodNames;

	public MySession() {
		map = new HashMap<String, String>();
		map.put("id", "id");          // key为实体类里面的属性名
		map.put("name", "name");      // value为对应表里面的字段名字
		map.put("age", "age");

		methodNames=new String[map.size()];
	}

	public void save(Object obj) {
		String sql = creatSQL();
		System.out.println(sql);

		Connection con = getConnection();	//创建用于连接数据库的Connection对象
		try {
			PreparedStatement st=(PreparedStatement) con.prepareStatement(sql);
			Method method=null;
			for (int j = 0; j < map.size(); j++) {
				method= obj.getClass().getMethod(methodNames[j]);
				Class<?> type=method.getReturnType();
				if (type.getName().equals("java.lang.String")) {
					String param=(String) method.invoke(obj);
					st.setString(j+1, param);
				}
				if (type.getName().equals("int")) {
					int param=(int) method.invoke(obj);
					st.setInt(j+1, param);
				}
				System.out.println(method.getName() + "--" + method.getReturnType());
			}
			st.execute();
			st.close();
			con.close();
		}catch (Exception e) {
		    // TODO: handle exception
			e.printStackTrace();
		}

	}

	/* 获取数据库连接的函数*/
	public  Connection getConnection() {
		Connection con = null;	//创建用于连接数据库的Connection对象
		try {
			Class.forName("com.mysql.jdbc.Driver");// 加载Mysql数据驱动
			con = DriverManager.getConnection(
					"jdbc:mysql://localhost:3306/webexample?" +
							"useUnicode=true&characterEncoding=UTF-8",
					"root","");// 创建数据连接
		} catch (Exception e) {
			System.out.println("数据库连接失败" + e.getMessage());
		}
		return con;	//返回所建立的数据库连接
	}

	public String creatSQL() {
		String sql;
		String str1 = new String();
		int index = 0;
		for (String key : map.keySet()) {
			str1 += key + ",";
			String v = map.get(key);
			// 下面是得到对应的bean中的get方法。也就是得到User类中的getId()、getUsername()、getPwd()方法。
			// 注意每个属性的get后面的第一个字母是大写,需要转换。
			v = "get" + Character.toUpperCase(v.charAt(0)) + v.substring(1);
			methodNames[index] = v; // 将方法保存在数组中。
			index++;
		}
		str1=str1.substring(0,str1.length()-1);

		String str2=new String();
		for (int i = 0; i < map.size(); i++)
			str2+="?,";
		str2=str2.substring(0, str2.length()-1);
		sql="insert into "+tableName +" ("+str1+ ") "+"values ("+str2+")";
		return sql;

	}

}

在MyHibernate里面测试

结果如下

其实这里面问题最多的在于反射知识的应用

自己动手写hibernate的更多相关文章

  1. 【原创】自己动手写工具----XSmartNote [Beta 3.0]

    一.前面的话 在动笔之前,一直很纠结到底要不要继续完成这个工具,因为上次给它码代码还是一年多之前的事情,参考自己动手写工具----XSmartNote [Beta 2.0],这篇博文里,很多园友提出了 ...

  2. 【原创】自己动手写控件----XSmartNote控件

    一.前面的话 在上一篇博文自己动手写工具----XSmartNote [Beta 3.0]中,用到了若干个自定义控件,其中包含用于显示Note内容的简单的Label扩展控件,用于展示标签内容的labe ...

  3. 【原创】自己动手写工具----XSmartNote [Beta 2.0]

    一.前面的话 在上一篇自己动手写工具----XSmartNote中,我简单介绍了这个小玩意儿的大致界面和要实现的功能,看了一下园子里的评论,评价褒贬不一,有人说“现在那么多云笔记的工具”,“极简版ev ...

  4. 【原创】自己动手写工具----签到器[Beta 2.0]

    一.前面的话 上一篇中基本实现了简单的签到任务,但是不够灵活.在上一篇自己动手写工具----签到器的结尾中,我设想了几个新增功能来提高工具的灵活程度,下面把新增功能点列出来看看: (1)新增其他的进程 ...

  5. 自己动手写ORM的感受

    之前看到奋斗前辈和时不我待前辈的自己动手写ORM系列博客,感觉讲解的通俗易懂,清晰透彻.作为一个菜鸟,闲来也想着自己写一个ORM,一来加深自己对 ORM的理解,以求对EF,NHibernate等ROM ...

  6. 自己动手写插件底层篇—基于jquery移动插件实现

    序言 本章作为自己动手写插件的第一篇文章,会尽可能的详细描述一些实现的方式和预备知识的讲解,随着知识点积累的一点点深入,可能到了后期讲解也会有所跳跃.所以,希望知识点不是很扎实的读者或者是初学者,不要 ...

  7. Python - 动手写个ORM

    Python - 动手写个ORM 任务: 模拟简单的ORM - Object Relational Mapping 为model添加create方法 代码很简单,直接上 字段类型类 class Fie ...

  8. 【转】自己动手写SC语言编译器

    自序 编译原理与技术的一整套理论在整个计算机科学领域占有相当重要的地位,学习它对程序设计人员有很大的帮助.我们考究历史会发现那些人人称颂的程序设 计大师都是编译领域的高手,像写出BASIC语言的BIL ...

  9. 自己动手写CPU之第九阶段(8)——MIPS32中的LL、SC指令说明

    将陆续上传新书<自己动手写CPU>,今天是第47篇. 9.7 ll.sc指令实现思路 9.7.1 实现思路 这2条指令都涉及到訪问链接状态位LLbit,能够将LLbit当做寄存器处理,ll ...

随机推荐

  1. 【vuejs深入二】vue源码解析之一,基础源码结构和htmlParse解析器

    写在前面 一个好的架构需要经过血与火的历练,一个好的工程师需要经过无数项目的摧残. vuejs是一个优秀的前端mvvm框架,它的易用性和渐进式的理念可以使每一个前端开发人员感到舒服,感到easy.它内 ...

  2. 用ECMAScript4 ( ActionScript3) 实现Unity的热更新 -- CustomYieldInstruction 自定义中断指令

    ActionScript3脚本引擎为了方便热更新逻辑开发,提供的从脚本继承Unity类库功能在一些情况下可以提供开发的便利. 这次来建立一个示例,演示一下如何在脚本中自定义协程中断指令 Unity中的 ...

  3. JavaScript基础知识从浅入深理解(一)

    JavaScript的简介 javascript是一门动态弱类型的解释型编程语言,增强页面动态效果,实现页面与用户之间的实时动态的交互. javascript是由三部分组成:ECMAScript.DO ...

  4. seaborn使用(绘图函数)

    seaborn使用(绘图函数) 数据集分布的可视化 分类数据的绘图 线性关系可视化 一.数据集分布的可视化 distplot kdeplot rugplot 1.distplot() 灵活的绘制单变量 ...

  5. git使用之错误分析及解决(持续更新)

    错误一: 使用 $ git push -u origin master 出现如下错误: error: src refspec master does not match any. error: fai ...

  6. python OptParse模块的用法详解

    OptParse模块的简单介绍 Python 有两个内建的模块用于处理命令行参数: 一个是 getopt只能简单处理 命令行参数: 另一个是 optparse,它功能强大,而且易于使用,可以方便地生成 ...

  7. android NDK的下载-文件太大

    需要FQ,建议使用VPN,下载前准备点时间配置网络环境.我的百度网盘好像有~~不过忘记地址了,改天共享,或者私聊我. 2015.4 Android 5.1 Android Studio https:/ ...

  8. 让你的代码减少三倍!使用kotlin开发Android(五) 监听器

    本文同步自 博主的私人博客wing的地方酒馆 在前面的博客中,有一个栗子,是点击按钮转跳的监听器. button.setOnClickListener { val user = User(" ...

  9. Linux 中交换空间 (swap)应该分多大才好?

    前一段时间,我们机房中一台Linux服务器运行缓慢,系统服务出现间歇性停止响应,让我过去处理一下这一问题,登录到服务器之后,发现此服务器的物理内存是16G,而最初装机的时候,系统管理人员却只分配了4G ...

  10. Programming In Scala笔记-第九章、控制抽象

    本章主要讲解在Scala中如何使用函数值来自定义新的控制结构,并且介绍Curring和By-name参数的概念. 一.减少重复代码 1.重复代码的场景描述 前面定义的函数,将实现某功能的代码封装到一起 ...