首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 数据库 > 其他数据库 >

自各儿动手模仿Hibernate写数据库框架

2012-08-21 
自己动手模仿Hibernate写数据库框架自己动手模仿Hibernate写数据库框架最近项目有点儿停滞,论文看的也比较

自己动手模仿Hibernate写数据库框架
自己动手模仿Hibernate写数据库框架
最近项目有点儿停滞,论文看的也比较浮躁,于是就打算重写下后台的框架,数据库部分模仿Hibernate随手写个小程序,当然还没有写完,不过最简单的功能已经能有了,打算把代码贴上来,后续不断的更新。
简单介绍下这个框架:采用DBCP连接池,然后实现了类似Hibernate的按对象插入、更新、删除等。当然还没有写生命周期、延迟加载这些,不过后续会慢慢的加上去,否则就太小儿科了不是么。这个框架是建立在我原有的一个BDUtil的小项目上的,当时做插入这些操作需要传SQL语句和参数,现在把这步也省略了,当然最大的好处就是不用写SQL。
下面就上代码:
Commons.java: DBCP连接池,返回Connection对象。

package org.gfg.dbutil.common;import java.io.IOException;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.util.Properties;import javax.sql.DataSource;import org.apache.commons.dbcp.BasicDataSourceFactory;@SuppressWarnings("static-access")public class Commons {private static DataSource dataSource;static {try {Properties prop = new Properties();prop.load(Commons.class.getClassLoader().getResourceAsStream("dbcpconfig.properties"));BasicDataSourceFactory factory = new BasicDataSourceFactory();dataSource = factory.createDataSource(prop);} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}public static Connection getConnection() throws SQLException {return dataSource.getConnection();}public static void close(ResultSet rs, PreparedStatement ps, Connection conn) {try {if (rs != null) {rs.close();}if (ps != null) {ps.close();}if (conn != null) {conn.close();}} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}


DbUtils.java:主要封装了最基本的CRUD操作。注意在query方法的参数中传入了IResultSetHandler,这个接口的主要功能是对返回的结果集做封装。
package org.gfg.dbutil.common;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import org.gfg.dbutil.handler.BeanHandler;import org.gfg.dbutil.handler.IResultSetHandler;public class DbUtils {public static void insert(String sql, Object[] params) throws SQLException {// insertConnection conn = null;PreparedStatement ps = null;ResultSet rs = null;try {conn = Commons.getConnection();ps = conn.prepareStatement(sql);for (int i = 0; i < params.length; i++) {ps.setObject(i + 1, params[i]);}ps.executeUpdate();} finally {Commons.close(rs, ps, conn);}}public static void update(String sql, Object[] params) throws SQLException {// updateDbUtils.insert(sql, params);}public static void delete(String sql, Object[] params) throws SQLException {// deleteDbUtils.insert(sql, params);}public static Object query(String sql, Object[] params,IResultSetHandler rsh) throws SQLException {Connection conn = null;PreparedStatement ps = null;ResultSet rs = null;try {conn = Commons.getConnection();ps = conn.prepareStatement(sql);for (int i = 0; i < params.length; i++) {ps.setObject(i + 1, params[i]);}rs = ps.executeQuery();return rsh.handler(rs);} finally {Commons.close(rs, ps, conn);}}public static Object load(String sql, Object[] params,Class<?> clazz) {IResultSetHandler rsh=new BeanHandler(clazz);Connection conn = null;PreparedStatement ps = null;ResultSet rs = null;try {conn = Commons.getConnection();ps = conn.prepareStatement(sql);for (int i = 0; i < params.length; i++) {ps.setObject(i + 1, params[i]);}rs = ps.executeQuery();return rsh.handler(rs);} catch (SQLException e) {e.printStackTrace();} finally {Commons.close(rs, ps, conn);}return null;}}


IResultSetHandler.java:接口,加工ResultSet结果,可以返回Model,List等,这个可以自行扩展。
package org.gfg.dbutil.handler;import java.sql.ResultSet;public interface IResultSetHandler {public Object handler(ResultSet rs);}


BeanHandler.java:实现了IResultSetHandler接口,主要还是运用了反射。
package org.gfg.dbutil.handler;import java.beans.PropertyDescriptor;import java.lang.reflect.Method;import java.sql.ResultSet;import java.sql.ResultSetMetaData;public class BeanHandler implements IResultSetHandler {private Class<?> beanClass;public BeanHandler(Class<?> beanClass) {this.beanClass = beanClass;}@Overridepublic Object handler(ResultSet rs) {try {if (!rs.next()) {return null;}// 用于封装数据的beanObject bean = beanClass.newInstance();ResultSetMetaData meta = rs.getMetaData();int columnCount = meta.getColumnCount();for (int i = 0; i < columnCount; i++) {String columnName = meta.getColumnName(i + 1);Object columnValue = rs.getObject(columnName);try {                 //属性修改器PropertyDescriptor pd = new PropertyDescriptor(columnName,bean.getClass());Method method = pd.getWriteMethod();method.invoke(bean, columnValue);} catch (Exception e) {continue;}}return bean;} catch (Exception e) {throw new RuntimeException(e);}}}


Session.java:取名字所幸和Hibernate一样了,很简单的利用了反正将运行时的状态给拿出来。
package org.gfg.dbutil.session;import java.lang.reflect.Field;import org.gfg.dbutil.common.DbUtils;public class Session {public void save(Object obj) { //session.saveint term=obj.getClass().getName().lastIndexOf(".")+1;StringBuffer sql = new StringBuffer("Insert into "+ obj.getClass().getName().substring(term) + " (");Field[] fields = obj.getClass().getDeclaredFields();int size = fields.length;Field field = null;Object[] params = new Object[size];try {for (int i = 0; i < size - 1; i++) {field = fields[i];field.setAccessible(true);//运行时 把private 转成 publicparams[i] = field.get(obj);sql.append(field.getName() + ",");}fields[size-1].setAccessible(true);params[size - 1] = fields[size - 1].get(obj);sql.append(fields[size - 1].getName() + ") VALUES (");for (int i = 0; i < size - 1; i++) {sql.append("? , ");}sql.append("?) ");String strSQL = new String(sql);DbUtils.insert(strSQL, params);//insert} catch (Exception e) {e.printStackTrace();}System.out.println(sql);for(Object objValue:params){System.out.print("  value:"+objValue);}}public void update(Object obj) {int term=obj.getClass().getName().lastIndexOf(".")+1;StringBuffer sql = new StringBuffer("UPDATE "+ obj.getClass().getName().substring(term) + " SET ");Field[] fields = obj.getClass().getDeclaredFields();int size = fields.length;Field field = null;Object[] params = new Object[size+1];try {for (int i = 0; i < size - 1; i++) {field = fields[i];field.setAccessible(true);//运行时 把private 转成 publicparams[i] = field.get(obj);sql.append(field.getName() + "=?,");}fields[size-1].setAccessible(true);params[size - 1] = fields[size - 1].get(obj);sql.append(fields[size - 1].getName() + "=? WHERE " +fields[0].getName()+"=?");params[size]=params[0];String strSQL = new String(sql);DbUtils.update(strSQL, params);} catch (Exception e) {e.printStackTrace();}System.out.println(sql);for(Object objValue:params){System.out.print("  value:"+objValue);}}public void delete(Object obj){int term=obj.getClass().getName().lastIndexOf(".")+1;StringBuffer sql = new StringBuffer("DELETE from  "+ obj.getClass().getName().substring(term) + " WHERE ");Field[] fields = obj.getClass().getDeclaredFields();sql.append(fields[0].getName()+"=?");Object[] params = new Object[1];try {fields[0].setAccessible(true);params[0]=fields[0].get(obj);String strSQL = new String(sql);DbUtils.delete(strSQL, params);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.println(sql);for(Object objValue:params){System.out.print("  value:"+objValue);}}public Object load(Class<?> clazz,Object uuid){Object obj=null;try {obj = clazz.newInstance();Field[] fields = obj.getClass().getDeclaredFields();Object[] params = new Object[1];int term=obj.getClass().getName().lastIndexOf(".")+1;StringBuffer sql = new StringBuffer("SELECT * from  "+ obj.getClass().getName().substring(term) + " WHERE "+fields[0].getName()+"=?");params[0]=uuid;String strSQL = new String(sql);obj=DbUtils.load(strSQL,params,clazz);System.out.println(sql);for(Object objValue:params){System.out.print("  value:"+objValue);}} catch (Exception e) {e.printStackTrace();}return obj;}}


然后是POJO对象,这里我还没有写映射,所以数据库还得自己建立,当然表名和类名一致,数据库字段名称和类的成员变量名一直。这里有个需要注意:建立POJO对象时,要将成员变量的第一个设置为数据库的索引,例如我这里用了ID做索引。
package org.gfg.dbutil.model;public class User {private int id;private  String name;private String pass;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 String getPass() {return pass;}public void setPass(String pass) {this.pass = pass;}}


最后是单元测试类:写个save和load方法的测试,其他的都差不多。
package test;import org.gfg.dbutil.model.User;import org.gfg.dbutil.session.Session;import junit.framework.TestCase;public class TestSession extends TestCase{public void testSessionSave(){User user=new User();user.setId(0);user.setName("Alin");user.setPass("123456");Session session=new Session();session.save(user);}public void testSessionLoad(){Session session=new Session();session.load(User.class, 1);//Clazz & ID}}


程序暂告一段落了,写这个文章的时候突然想起来,好多模式还没用上去,不过这样的小东西应付应付一般的也够用了,当然还需要完善很多东西,等有空了接着把他写完。最后面会附下载链接,一个DEMO。


以上只是一种思路。个人愚见,谢谢观看。
本文原创,转载请指明出处,谢谢。                    
 

热点排行