自各儿动手模仿Hibernate写数据库框架
自己动手模仿Hibernate写数据库框架
最近项目有点儿停滞,论文看的也比较浮躁,于是就打算重写下后台的框架,数据库部分模仿Hibernate随手写个小程序,当然还没有写完,不过最简单的功能已经能有了,打算把代码贴上来,后续不断的更新。
简单介绍下这个框架:采用DBCP连接池,然后实现了类似Hibernate的按对象插入、更新、删除等。当然还没有写生命周期、延迟加载这些,不过后续会慢慢的加上去,否则就太小儿科了不是么。这个框架是建立在我原有的一个BDUtil的小项目上的,当时做插入这些操作需要传SQL语句和参数,现在把这步也省略了,当然最大的好处就是不用写SQL。
下面就上代码:
Commons.java: DBCP连接池,返回Connection对象。
DbUtils.java:主要封装了最基本的CRUD操作。注意在query方法的参数中传入了IResultSetHandler,这个接口的主要功能是对返回的结果集做封装。
IResultSetHandler.java:接口,加工ResultSet结果,可以返回Model,List等,这个可以自行扩展。
BeanHandler.java:实现了IResultSetHandler接口,主要还是运用了反射。
Session.java:取名字所幸和Hibernate一样了,很简单的利用了反正将运行时的状态给拿出来。
然后是POJO对象,这里我还没有写映射,所以数据库还得自己建立,当然表名和类名一致,数据库字段名称和类的成员变量名一直。这里有个需要注意:建立POJO对象时,要将成员变量的第一个设置为数据库的索引,例如我这里用了ID做索引。
最后是单元测试类:写个save和load方法的测试,其他的都差不多。
程序暂告一段落了,写这个文章的时候突然想起来,好多模式还没用上去,不过这样的小东西应付应付一般的也够用了,当然还需要完善很多东西,等有空了接着把他写完。最后面会附下载链接,一个DEMO。
以上只是一种思路。个人愚见,谢谢观看。
本文原创,转载请指明出处,谢谢。
自己动手模仿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 block e.printStackTrace(); } catch (Exception e) { // TODO Auto-generated catch block e.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 block e.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 {// insert 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]); } ps.executeUpdate(); } finally { Commons.close(rs, ps, conn); } } public static void update(String sql, Object[] params) throws SQLException {// update DbUtils.insert(sql, params); } public static void delete(String sql, Object[] params) throws SQLException {// delete DbUtils.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; } @Override public Object handler(ResultSet rs) { try { if (!rs.next()) { return null; } // 用于封装数据的bean Object 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.save int 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 转成 public params[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 转成 public params[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 block e.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。
以上只是一种思路。个人愚见,谢谢观看。
本文原创,转载请指明出处,谢谢。
1 楼
elf8848
2012-05-07
2 楼
ielts0909
2012-05-08
elf8848 写道