反射封装JDBC——hibernate DDL 实现原理
2013-10-15 10:32
155 查看
反射封装JDBC——hibernate DDL 实现原理
发表回复0.00 / 5 5 1 / 5 2 / 5 3 / 5 4 / 5 5 / 5 0 votes, 0.00 avg. rating (0% score) 现在学习java的人实在是太多了,什么培训学校,什么高校,基本上是学习java的,以至于现在java工资比较低。我记得上次我去面试的时候, 居然几个假冒的项目经理说struts底层不是用servlet,当时我觉得这项目经理未必也太….,也许我理解错误了吧,struts底层不是采用servlet,本来从事java已经2年了,但是只是入门阶段,所以写的东西有很多错误,希望大家可以指出来,我也好学习学习。 做java的人肯定学过什么S*SH框架吧,但是很多人都只会使用罢了,很少的人会去看源码,其实这些框架真正的价值是在于整个架构,而不是在于使用罢了,如果你做为一个程序员,底层是怎么实现的都不知道,那又有什么作用呢,在此我通过反射写了一个类似于hibernate实现(DDL),同时我也添加了一些新的东西,可能是我的想法和hibernate作者有点出入吧,就是在更新方法的时候。大家仔细看看就知道了。 首先看一下项目结构,下面有连接,我直接把源码上传上去,大家可以直接下载来看 (因为我没有实现hibernate的自动创建表,所以需要自己建立表,建立表参考UsersBean类)下载链接http://files.cnblogs.com/bolobeach/JDBCHelper.rar 一、闲话少说了吧 ,我相信看我写的博客都知道,我比较喜欢直接上源码来看,连接数据库最基本上的操作我封装到一个类里面,这个基本上没有什么讲的,【如果你采用java7的话不需要关闭数据库资源,JVM会自动关闭的,这是java7的新特性,如果不明白的请看我上一篇博文】下面请看此代码 package com.zh.db; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; /** * @Copyright (C), 2010-2030 淘青春团队 * @FileName DB.java * @version 1.0 * @Description: 【用来操作数据库的类】 * @Author 张兵 * @Date: 2013-8-3:下午8:09:19 * @Modification User: 程序修改时由开发人员编写 * @Modification Date: 程序修改时间 * @mailto bolobeach@gmail.com */ public class DB { private String DBDrive = "com.mysql.jdbc.Driver"; private String DBUrl = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8"; private String DBUser = "root"; private String DBPassword = "XXXXXX"; private ResultSet _rs = null; private Connection _conn = null; private Statement _stmt = null; /** * 执行一则更新语句,返回主键值 * * @param sql * @return */ public Connection getConn() { try { Class.forName(DBDrive); _conn = DriverManager.getConnection(DBUrl, DBUser, DBPassword); System.out.println("数据库可以使用了!!!!"); } catch (Exception e) { System.out.println("---------出现异常,获取连接失败--------"); e.printStackTrace(); } return _conn; } public int executeUpdate(String sql) { int result = -1; try { // 执行sql _stmt = getConn().createStatement(); _stmt.executeUpdate(sql,Statement.RETURN_GENERATED_KEYS); // 获取主键 _rs = _stmt.getGeneratedKeys(); while (_rs.next()) { // 获取最后一个主键值 result = _rs.getInt(1); } } catch (Exception e) { e.printStackTrace(); } finally { this.colse(); } return result; } public ResultSet executeQuery(String sql) { try { // 执行sql _stmt = getConn().createStatement(); _rs = _stmt.executeQuery(sql); } catch (Exception e) { e.printStackTrace(); } return _rs; } /** * 获取数据库连接 * * @return */ // 关闭数据库操作。。。。 public boolean colse() { try { if (_rs != null) { _rs.close(); } if (_stmt != null) { _stmt.close(); } if (_conn != null) { _conn.close(); } return true; } catch (SQLException e) { System.out.println("关闭失败。。。。。"); e.printStackTrace(); return false; } } } 二、做这个帮助类是必不可少的,帮助类下面主要有javabean 成员变量里面首字母转为小写,或者大写,以及怎么得到一个表里面的主键,hibernate底层是没有实现的,可能是因为效率的原因吧。 package com.zh.reflectUtil; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import com.zh.basic.BasicDao; import com.zh.basic.BasicImpl; import com.zh.bean.UsersBean; import com.zh.db.DB; /** * @Copyright (C), 2010-2030 淘青春团队 * @FileName ReflectUtil.java * @version 1.0 * @Description: 【java反射的until帮助类】 * @Author 张兵 * @Date: 2013-8-3:下午8:23:43 * @Modification User: 程序修改时由开发人员编写 * @Modification Date: 程序修改时间 * @mailto bolobeach@gmail.com */ public class ReflectUtil { public static void main(String[] args) { BasicDao basicDao = new BasicImpl(); //UsersBean usersBean = new UsersBean(1, "张兵", "123", "390125214@qq.com"); UsersBean usersBean = new UsersBean(); usersBean.setEmail("390125214@qq.com"); usersBean.setPassword("123"); usersBean.setUserName("张fff兵"); usersBean.setUsersId(2); try { int a = basicDao.update(usersBean); System.out.println("zuihou.."+a); } catch (Exception e) { e.printStackTrace(); } /*try { getPK("usersBean"); } catch (SQLException e) { e.printStackTrace(); }*/ } /** * 把第一个字母转换为大写 * * @param fildeName * @return * @throws Exception */ public static String getMethodName(String fildeName) throws Exception { byte[] items = fildeName.getBytes(); items[0] = (byte) ((char) items[0] - 'a' + 'A'); return new String(items); } /** * 把头字母转为小写最优化的 * @param tableName * @return * @throws Exception */ public static String getTableName(String tableName) throws Exception{ byte[] temp = tableName.getBytes(); temp[0] = (byte) ((char) temp[0] +32); return new String(temp); } /** * 通过表的名字,得到表的主键 * @param tableName 表明 * @return list对象 (考虑联合主键) * @throws SQLException */ public static List<Object> getPK(String tableName) throws SQLException{ List<Object> list = new ArrayList<>(); DB db = new DB(); Connection connection = db.getConn(); DatabaseMetaData data = connection.getMetaData(); ResultSet resultSet = data.getPrimaryKeys(null, null, tableName.toUpperCase()); while (resultSet.next()) { list.add(resultSet.getObject(4)); } return list; } } 三、因为我采用面向结构编程, 所以有一个接口类,在这里我就不用接口类了,直接上实现类的源码。这个才是此博文的重点。 保存方法以及删除方法在这里我就不用讲了吧,代码大家应该都看的明明白白的,也许有些人对java反射不是很了解,可以去查查资料。我采用的就是对sql语句进行拼接, 所以保存语句以及删除语句都本质上都和hibernate一样是jdbc罢了。但是在update()方法中有些不一样,hibernate的更新原理是这样:首先hibernate先会执行一个select操作,到数据库中查找当前要update操作的对象的主键是否存在,类似于:select id from table where id=XXX,如果查找到了改id,就说明该对象是一个持久化对象,如果该对像的某些属性变化了,hibernate就会自动的执行update操作,同步数据库中的该对象。如果hibernate没有查找到该id,就说明该对象是一个游离的对象,hibernate就会执行insert操作。根据这些,就可以找找是不是要update的对象的id在数据库中不存在,或是更改的该对象的id。这些都是执行insert而不是update。 但是我可能考虑的没有那么多直接默认表结构里面有主键,首先查询出主键,把数据库那个字段表示主键查询出来,然后在根据sql语句进行跟新, 如果没有主键的对应的值话,就返回false,不做更新操作, 同时也不做insert操作。 package com.zh.basic; import java.lang.reflect.Field; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSetMetaData; import java.util.ArrayList; import java.util.List; import com.zh.db.DB; import com.zh.reflectUtil.ReflectUtil; /** * @Copyright (C), 2010-2030 淘青春团队 * @FileName BasicImpl.java * @version 1.0 * @Description: 用于详细说明此程序文件完成的主要功能 * @Author 张兵 * @Date: 2013-8-3:下午8:22:31 * @Modification User: 程序修改时由开发人员编写 * @Modification Date: 程序修改时间 * @mailto bolobeach@gmail.com */ public class BasicImpl extends DB implements BasicDao { ReflectUtil reflectUtil = new ReflectUtil(); public int save(Object object) throws Exception { int reNumber = -1; String values = ""; String temp = ""; Class<?> clazz = object.getClass(); ArrayList<Object> params = new ArrayList<Object>(); Field[] fields = clazz.getDeclaredFields(); //在这里必须设置,不然不可以得到私有变量 Field.setAccessible(fields, true); int fieldsLength = fields.length; for (int i = 0; i < fieldsLength; i++) { Field field = fields[i]; values +=field.getName()+","; Object val = field.get(object); temp+="?,"; params.add(val); } String tableName = clazz.getSimpleName(); String sql = "insert into "+reflectUtil.getTableName(tableName)+"("+values.substring(0, values.length()-1)+") values("+temp.substring(0,temp.length()-1)+")"; System.out.println(sql); try { Connection conn = this.getConn(); PreparedStatement ps = null; ps = conn.prepareStatement(sql); for (int i = 0; i < params.size(); i++) { System.err.println(params.get(i)); ps.setObject(i+1, params.get(i)); } reNumber = ps.executeUpdate(); this.colse(); } catch (Exception e) { e.printStackTrace(); } return reNumber; } public int update(Object object) throws Exception{ int reNumber = -1; String values = ""; Class<?> clazz = object.getClass(); ArrayList<Object> params = new ArrayList<Object>(); Field[] fields = clazz.getDeclaredFields(); Field.setAccessible(fields, true); int fieldsLength = fields.length; String tableName = this.reflectUtil.getTableName(clazz.getSimpleName()); List<Object> list = this.reflectUtil.getPK(tableName); Object pkValue = null; Object pk = null; for (Object object2 : list) { pk = object2; for (int i = 0; i < fieldsLength; i++) { Field field = fields[i]; if (field.getName().equals(object2)) { values +=field.getName()+"=?,"; pkValue = field.get(object); }else { values +=field.getName()+"=?,"; } Object val = field.get(object); params.add(val); } } String sql = "update "+tableName+" set "+values.substring(0,values.length()-1)+" where "+pk+"=?"; System.out.println(sql); try { Connection conn = this.getConn(); PreparedStatement ps = null; ps = conn.prepareStatement(sql); int temp1 = params.size(); for (int i = 0; i < temp1; i++) { System.err.println(params.get(i)); ps.setObject(i+1, params.get(i)); } ps.setObject(temp1+1, pkValue); reNumber = ps.executeUpdate(); this.colse(); } catch (Exception e) { e.printStackTrace(); } return reNumber; } public int deleteById(Class<?> clazz,Object id) throws Exception{ int reNumber = -1; String tableName = this.reflectUtil.getTableName(clazz.getSimpleName()); List<Object> list = this.reflectUtil.getPK(tableName);//得到主键 Connection conn = this.getConn(); for (Object object : list) { String sql = "delete from "+tableName+" where "+object+"=?"; PreparedStatement ps = null; ps = conn.prepareStatement(sql); ps.setObject(1, id); reNumber = ps.executeUpdate(); reNumber = 1; this.colse(); } return reNumber; } } |
相关文章推荐
- hibernate 的Session中save和load,close方法的底层实现原理
- 实现在Hibernate中的分页查询原理解读
- Hibernate实现分页查询的原理分析
- Hibernate框架ORM的实现原理
- Hibernate框架ORM的实现原理
- hibernate延迟加载的原理与实现
- Hibernate的setFirstResult,setMaxResults实现数据库分页原理
- 菜鸟学SSH(十五)——简单模拟Hibernate实现原理
- ThreadLocal的实现原理,及使用实例,解决spring,hibernate非web项目下的懒加载 no session or session was closed(2)!
- Hibernate实现分页查询的原理分析
- Hibernate学习02---Hibernate原理分析和模拟其实现
- Hibernate框架ORM的实现原理
- Hibernate框架ORM的实现原理
- Hibernate乐观锁的实现原理剖析与使用乐观锁时的注意点
- Hibernate框架ORM的实现原理
- 实现Hibernate分页查询原理解读
- 实现Hibernate分页查询原理解读
- 菜鸟学SSH(十五)——简单模拟Hibernate实现原理
- Hibernate框架ORM的实现原理
- Hibernate框架ORM的实现原理-不是技术的技术