自己动手模仿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。
以上只是一种思路。个人愚见,谢谢观看。
本文原创,转载请指明出处,谢谢。
分享到:
相关推荐
本项目旨在模仿Hibernate的核心功能,以加深对ORM的理解并锻炼Java编程能力。 首先,让我们了解Hibernate的基本概念。Hibernate是一个开源的ORM框架,它允许开发人员将Java类映射到数据库表,Java对象映射到数据库...
标题 "sorm.zip_JEM_SORM_模仿hibernate库" 暗示这是一个与ORM(对象关系映射)框架相关的项目,它模仿了著名的Java持久化库Hibernate。ORM是编程领域中的一个重要概念,它允许开发者用面向对象的方式来操作数据库,...
标题提到的“数据库连接池以及hibernate对各种连接池的整合”是指在Java应用中,特别是使用Hibernate作为持久层框架时,如何集成和配置不同的数据库连接池技术。以下是一些主要的开源数据库连接池及其特点: 1. **...
Java模仿Hibernate是一个学习过程...总之,Java模仿Hibernate是一项综合性的任务,涵盖了数据库操作、对象关系映射、查询语言解析等多个领域。通过这样的实践,我们可以加深对ORM框架的理解,提升自己的Java编程能力。
1 ORM框架——模仿Hibernate 2 MVC框架——模仿struts2 3 IOC框架——模仿Spring 4 框架整合及项目实例 使用技术: 开发语言:Java 开发工具:Eclipse,MyEclipse 数据库:MySQL 数据库工具:Navicat 建模工具:...
而Hibernate则是一个对象关系映射(ORM)框架,它简化了数据库操作,允许开发者通过Java对象来操作数据库,减少了对SQL的直接使用。 标题中的"spring+hibernate"表明这是一个将两者结合使用的项目。Spring和...
1. **JDBC基础**:在模仿Hibernate之前,我们需要了解JDBC(Java Database Connectivity)的基本用法,包括连接数据库、执行SQL语句、处理结果集等。这通常是所有持久层框架的基础,理解JDBC有助于我们了解Hibernate...
【JavaEE Struts2 Hibernate框架例子】是一个典型的Java企业级应用程序开发示例,它结合了三个主流的开源框架——Struts2、Hibernate和...通过深入研究和模仿这个示例,开发者可以提升自己的JavaEE Web应用开发能力。
在IT行业中,SSH框架是Java Web开发中常用的一种组合,由Spring、Struts2和Hibernate三个开源框架组成。...通过学习和模仿这个项目,开发者可以进一步熟悉SSH框架的工作原理,提高自己的编程技能。
在Java开发中,Hibernate是一个非常重要的对象关系映射(ORM)框架,它允许开发者通过面向对象的方式操作数据库,而无需直接编写SQL语句。本文将深入探讨如何模仿Hibernate生成SQL语句,以及如何利用Java反射技术来...
该项目是一个模仿当当网的在线商城系统,采用的是经典的Java Web开发框架——Struts2和持久层框架Hibernate。Struts2作为MVC(Model-View-Controller)架构的一部分,负责处理用户请求,控制应用程序的流程,而...
通过分析和模仿这个项目,你可以提升自己的Web开发技能,理解前后端交互的流程,以及如何有效地使用ORM框架来处理数据库操作。同时,这也是一个很好的实践项目,可以帮助你更好地掌握Web开发的全貌。
【标题】:“BBS论坛(糗事百科+SSH框架+数据库文件)”指的是一个基于SSH框架开发的在线论坛系统,其设计灵感来源于知名的糗事分享网站糗事百科。SSH是Struts、Spring和Hibernate三个开源Java框架的组合,常用于...
【hibernate(1)】是一个模仿Hibernate ORM框架的小型项目,主要目的是为了教学和深入理解Hibernate的核心概念以及ORM(对象关系映射)思想。在这个项目中,开发者将能够亲手实践如何实现类似Hibernate的功能,从而更...
Hibernate是一个强大的对象关系映射(ORM)框架,它简化了Java应用与数据库之间的交互。在本实例中,Hibernate用于处理文档的存储和检索,将Java对象与数据库表进行映射,从而减少了手动编写SQL语句的工作量。 **4....
在这个名为“模拟hibernate注解功能”的项目中,我们将探讨如何利用自定义注解和反射技术来模仿Hibernate的注解功能。 首先,让我们理解一下Hibernate的注解。Hibernate支持JPA(Java Persistence API)标准,其中...
标题中的“自己写的一个持久化层”指的是作者创建了一个用于数据存储和检索的软件组件,类似于知名的ORM(对象关系映射)框架Hibernate。持久化层是应用程序中的一个关键部分,它负责将业务对象的数据保存到数据库中...
**Hibernate原生通用DAO**是基于Hibernate框架设计的一种简化数据访问操作的方式,它模仿了Spring框架中的`HibernateTemplate`类,旨在提供一个简单易用的DAO(Data Access Object)层,方便开发人员进行数据库操作...