实现简单的ORM功能,类似Hibernate功能


本人水平不足,菜鸟一个,说的有错希望各位前辈给予指导。
之前学习Hibernate时,发现Hibernate很好用,省了很多编写SQL的时间。
但是自己平常做一些练习时基本都是小东西,使用Hibernate便觉得大材小用了,所以自己试着实现类似Hibernate的一些简单功能,当然我写的只是形似而神不似。

以下是我的测试结果:
		User user = new User();
		user.setName("HHZoog");
		user.setPwd("HHZoog");
		user.setMusic_box("12");
		
		HibernateDao.save(user);

插入结果:

		User user = new User();
		user.setId(22);
		user.setName("HHZoog");
		user.setPwd("OOOOOO");
		user.setMusic_box("12");
		
		HibernateDao.update(user);

修改结果:

		User user = new User();
		user.setId(22);
		user.setName("HHZoog");
		user.setPwd("OOOOOO");
		user.setMusic_box("12");
		
		HibernateDao.delete(user);

删除结果:删除成功

User user = (User)HibernateDao.get(User.class, 23);
		System.out.println(user.getId() + " | " +user.getName() + " | " +user.getPwd());

查找结果:

find查找测试:
		String sql = "select * from user where id = 23";
		List<Object> lists = HibernateDao.find(sql, User.class);
		for(int i = 0 ; i < lists.size(); i++)
		{
			User user = (User)lists.get(i);
			System.out.println(user.getId() + " | " +user.getName() + " | " +user.getPwd());
		}

测试结果图片:

以下是各个类的使用方法:
ResultSetToObject类事件数据库操作返回的ResultSet结果集转为List<Object>对象
public class ResultSetToObject
{
	public static List<Object> turnToObject(ResultSet resultSet,
			Class<?> objClass)
	{
		/** 存储转化后的实体类 */
		List<Object> listObjs = new ArrayList<Object>();

		/** resultSet数据表中的字段名称 */
		String[] columnNames = null;

		/** resultSet数据表中对应字段的数据类型 */
		String[] columnTypes = null;

		try
		{
			if (resultSet == null)
			{
				return listObjs;
			} else
			{
				ResultSetMetaData metaResult = resultSet.getMetaData();
				int length = metaResult.getColumnCount();
				columnNames = new String[length];
				columnTypes = new String[length];
				for (int i = 0; i < columnNames.length; i++)
				{
					columnNames[i] = metaResult.getColumnName(i + 1);
					columnTypes[i] = metaResult.getColumnClassName(i + 1);
				}

				while (resultSet.next())
				{
					try
					{
						/* 实例化实体类 */
						Object obj = objClass.newInstance();

						/* 根据字段名调用实体类中的set方法 */
						for (int j = 0; j < columnNames.length; j++)
						{
							Method method = objClass.getDeclaredMethod("set"
									+ FunctionUtils.upInitial(columnNames[j]),
									FunctionUtils.paraTypeClass(columnTypes[j]));
							method.invoke(obj, resultSet
									.getObject(columnNames[j]));
						}

						listObjs.add(obj);
					} catch (InstantiationException e)
					{
						e.printStackTrace();
					} catch (IllegalAccessException e)
					{
						e.printStackTrace();
					} catch (SecurityException e)
					{
						e.printStackTrace();
					} catch (NoSuchMethodException e)
					{
						e.printStackTrace();
					} catch (IllegalArgumentException e)
					{
						e.printStackTrace();
					} catch (InvocationTargetException e)
					{
						e.printStackTrace();
					}
				}
			}

			/* 关闭结果集 */
			resultSet.close();

		} catch (SQLException e)
		{
			e.printStackTrace();
		}
		return listObjs;
	}

}


FunctionUtils类提供一些常用的方法
public class FunctionUtils
{
	/**
	 * 将首字母变为大写
	 * 
	 * @param str
	 * @return
	 */
	public static String upInitial(String str)
	{
		char[] chars = str.toCharArray();
		chars[0] = Character.toUpperCase(chars[0]);
		return new String(chars);
	}

	/**
	 * 字段的数据类型
	 * 
	 * @param str
	 * @return
	 */
	public static Class<?> paraTypeClass(String str)
	{
		if (str.equals("java.lang.String"))
		{
			return java.lang.String.class;
		} else if (str.equals("java.lang.Integer"))
		{
			return java.lang.Integer.class;
		} else if (str.equals("java.lang.Character"))
		{
			return java.lang.Character.class;
		} else if (str.equals("java.lang.Double"))
		{
			return java.lang.Double.class;
		} else if (str.equals("java.lang.Short"))
		{
			return java.lang.Short.class;
		} else if (str.equals("java.lang.Byte"))
		{
			return java.lang.Byte.class;
		} else if (str.equals("java.lang.Float"))
		{
			return java.lang.Float.class;
		} else if (str.equals("java.lang.Boolean"))
		{
			return java.lang.Boolean.class;
		} else if (str.equals("java.util.Date"))
		{
			return java.util.Date.class;
		}
		return null;
	}

}


BaseOperatorDao类是基本的数据操作类,执行传递过来的Sql语句;
/**
 * 数据基本操作类
 * @author HHZ
 *
 */
public class BaseOperatorDao 
{
	private static Statement statement = null;

	/**
	 * 使用Statement对象对数据操作
	 * 主要是查询
	 * @param sql
	 * @return
	 */
	public static ResultSet selectData(String sql) 
	{
		ResultSet resultSet = null;
		try 
		{
			    Connection conn =  ConnectDB.connToDB();
				statement = conn.createStatement();
				resultSet = statement.executeQuery(sql);
				return resultSet;
		} catch (SQLException e)
		{
			e.printStackTrace();
		}
		
		ConnectDB.releaseDB(resultSet, statement, ConnectDB.conn);
		
		return resultSet;
	}
	
	/**
	 * 使用Statement对象操作数据
	 * 主要针对数据的增删改
	 * @param sql
	 * @return
	 */
	public static int delOrSaveOrUpdateData(String sql)
	{
		try 
		{
			statement = ConnectDB.connToDB().createStatement();
			return statement.executeUpdate(sql);
			
		} catch (SQLException e)
		{
			e.printStackTrace();
		}
		
		ConnectDB.releaseDB(null, statement, ConnectDB.conn);
		
		return 0;
	}
}


ConnectDB类是连接数据库的操作类:

/**
 * 连接数据库
 * @author HHZ
 * 
 */
public class ConnectDB
{
	/** 数据库用户名 */
	private static String DB_uName = "root";

	/** 数据库用户密码 */
	private static String DB_uPwd = "mysqladmin";

	/** 数据库驱动 */
	private static String DB_Driver = "com.mysql.jdbc.Driver";

	/** 数据库连接路径 */
	private static String DB_Url = "jdbc:mysql://localhost:3306/Pluto";
	
	/**数据库连接对象*/
	public static Connection conn = null;

	private ConnectDB()
	{

	}

	/**
	 * 加载数据库驱动
	 */
	static
	{
		try
		{
			Class.forName(DB_Driver);
		} catch (ClassNotFoundException e)
		{
			e.printStackTrace();
		}
	}

	/**
	 * 连接数据库,并返回数据库连接对象
	 * @return
	 */
	public static Connection connToDB()
	{
		try
		{
				conn = DriverManager.getConnection(DB_Url, DB_uName, DB_uPwd);

		} catch (SQLException e)
		{
			e.printStackTrace();
		}

		return conn;
	}

	/**
	 * 关闭数据库,释放资源
	 * @param resultSet
	 * @param statement
	 * @param conn
	 */
	public static void releaseDB(ResultSet resultSet, Statement statement,
			Connection conn)
	{

		try
		{
			if (resultSet != null)
			{
				resultSet.close();
			}
		} catch (SQLException e)
		{
			e.printStackTrace();
		} finally
		{
			try
			{
				if(statement != null)
				{
					statement.close();
				}
			} catch (SQLException e)
			{
				e.printStackTrace();
			} finally
			{
				try
				{
					conn.close();
				} catch (SQLException e)
				{
					e.printStackTrace();
				}
			}
		}
	}
}


HibernateDao提供类似Hibernate简单操作的功能:
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.util.List;
import com.music.utils.FunctionUtils;
import com.music.utils.ResultSetToObject;

/**
 * 数据库持久层封装操作类
 * @author HHZ
 *
 */
public class HibernateDao
{ 
	
	/**
	 * 保存对象
	 * @param object
	 */
	public static void save(Object object)
	{
		Class<?> objClass = object.getClass();       
		Field[] fields = objClass.getDeclaredFields();  
		
		/*构建SQL语句*/
		StringBuffer sql = new StringBuffer("insert into ");  
		StringBuffer values = new StringBuffer("values(");
		
		/*数据库名称*/
		Field tableName = null;
		
		try
		{
			/*根据实体类中的tableName属性获得数据库名称*/
			tableName = objClass.getDeclaredField("tableName");
			
			/*拼接SQL语句*/
			sql.append(tableName.get(object));
			sql.append("(");
			
			/*根据传入的object对象获取到属性的值,并拼接到SQL语句中*/
			for(int i = 0 ; i < fields.length ; i++)
			{
				/*但object的属性名为tableName,id,primaryKey时,则不将其拼接到SQL语句中*/
				if(fields[i].getName().equals("tableName") || fields[i].getName().equals("id") || fields[i].getName().equals("primaryKey"))
				{
					
				}else
				{
				   	sql.append(fields[i].getName());
				   	sql.append(",");
				   	
				   	/*获得object对应属性的字段名的getXxxx()方法*/
					Method method = objClass.getDeclaredMethod
					("get"+FunctionUtils.upInitial(fields[i].getName()));
					
					/*获得此objec字段的值*/
					Object value = method.invoke(object);
					
					/*如果值为空,则SQL语句中的值则为空*/
					if(value == null)
					{
						values.append("null");
						values.append(",");
					}
					
					/*获得此字段对应的数据类型*/
					else if(fields[i].getType() == java.lang.String.class)
					{
					    values.append("'");
					    values.append(value);
					    values.append("'");
					    values.append(",");
					}else
					{
						values.append(value);
						values.append(",");
					}
				}
			}
			
		} catch (SecurityException e)
		{
			e.printStackTrace();
		} catch (NoSuchFieldException e)
		{
			e.printStackTrace();
		} catch (IllegalArgumentException e)
		{
			e.printStackTrace();
		} catch (IllegalAccessException e)
		{
			e.printStackTrace();
		} catch (NoSuchMethodException e)
		{
			e.printStackTrace();
		} catch (InvocationTargetException e)
		{
			e.printStackTrace();
		}
		
		/*删除末尾一个逗号*/
		sql.delete(sql.length()-1, sql.length());
		sql.append(")");
		sql.append(" ");
		values.delete(values.length()-1, values.length());
		values.append(")");
		
		/*拼接成一条完整的SQL语句*/
		String resultSql = sql.toString() + values.toString();
		
		/*执行SQL语句操作*/
		BaseOperatorDao.delOrSaveOrUpdateData(resultSql);
		
		System.out.println(resultSql);
	}

	/**
	 * 根据提供的SQL和实体类查找数据并返回List<Object>
	 * @param sql
	 * @param objClass
	 * @return
	 */
	public static List<Object> find(String sql,Class<?> objClass)
	{
		return ResultSetToObject.turnToObject(BaseOperatorDao.selectData(sql),objClass);
	}

	/*根据主键查找数据*/
	public static Object get(Class<?> objClass,Object key)
	{
		
		StringBuffer sql = new StringBuffer("select * from ");
		Object object = null;
		
		try
		{
			Field tableName = objClass.getDeclaredField("tableName");
			Field primaryKey = objClass.getDeclaredField("primaryKey");
			
			/*拼接数据库名到SQL语句中*/
			sql.append(tableName.get(objClass));
			
			/*获得主键数据类型,如果是string类型则加单引号*/
			if(primaryKey.getType().equals("java.lang.String.class"))
			{
				sql.append(" where "+primaryKey.get(objClass)+" ='"+key.toString()+"'");
			}else
			{
				sql.append(" where "+primaryKey.get(objClass)+" ="+key.toString());
			}

			System.out.println(sql.toString());
			
			/*执行SQL语句后返回List对象*/
			List<Object> listObjects = ResultSetToObject.turnToObject(BaseOperatorDao.selectData(sql.toString()),objClass);
			
			/*取得第一条记录,即查找到数据*/
			object = listObjects.get(0);
			
		} catch (SecurityException e)
		{
			e.printStackTrace();
		} catch (NoSuchFieldException e)
		{
			e.printStackTrace();
		} catch (IllegalArgumentException e)
		{
			e.printStackTrace();
		} catch (IllegalAccessException e)
		{
			e.printStackTrace();
		}
		
		return object;
	}

	/**
	 * 删除记录
	 * @param object
	 */
	public static void delete(Object object)
	{
		
		StringBuffer sql = new StringBuffer("delete from ");
		
		/*获得对象的Class类型*/
		Class<?> objClass = object.getClass();
		
		/*对象申明的属性*/
		Field filed;
		
		/*对象申明的方法*/
		Method method = null;
		
		try
		{
			/*获得主键名称*/
			Field primaryKey = objClass.getDeclaredField("primaryKey");
			String keyName = (String) primaryKey.get(objClass);
			
			/*将keyName首字母转为大写,并获得主键的get方法*/
			method = objClass.getDeclaredMethod("get"+FunctionUtils.upInitial(keyName));
			
			/*获得数据名称,并拼接到SQL语句中*/
			filed = objClass.getDeclaredField("tableName");
			sql.append(filed.get(objClass));
			
			if(primaryKey.getType().equals("java.lang.String.class"))
			{
				sql.append(" where "+keyName+" = '"+method.invoke(object)+"'");
			}else
			{
				sql.append(" where "+keyName+" = "+method.invoke(object));
			}
			
			BaseOperatorDao.delOrSaveOrUpdateData(sql.toString());
		} catch (SecurityException e)
		{
			e.printStackTrace();
		} catch (NoSuchFieldException e)
		{
			e.printStackTrace();
		} catch (IllegalArgumentException e)
		{
			e.printStackTrace();
		} catch (IllegalAccessException e)
		{
			e.printStackTrace();
		} catch (NoSuchMethodException e)
		{
			e.printStackTrace();
		} catch (InvocationTargetException e)
		{
			e.printStackTrace();
		}
		
		System.out.println(sql.toString());
	}

	/**
	 * 根据SQL删除记录
	 * @param sql
	 * @return
	 */
	public static int delete(String sql)
	{
		return BaseOperatorDao.delOrSaveOrUpdateData(sql);
	}

	/**
	 * 更新记录
	 * @param object
	 */
	public static void update(Object object)
	{
		/*获得对象的类型*/
		Class<?> objClass = object.getClass();
		
		/*待拼接SQL语句*/
		StringBuffer sql = new StringBuffer("update ");
		StringBuffer whereSql = new StringBuffer(" where ");
		
		/*获得申明的属性*/
		Field[] fields = objClass.getDeclaredFields();
		
		
		try
		{
			Field tableName = objClass.getDeclaredField("tableName");
			Field primaryKey = objClass.getDeclaredField("primaryKey");
			
			/*获得主键的名称*/
			String keyName = (String)primaryKey.get(objClass);
			
			/*将主键拼接到SQL语句中*/
			whereSql.append(keyName);
			whereSql.append("= ");
			sql.append(tableName.get(objClass));
			sql.append(" set ");
			
			for(int i = 0 ; i < fields.length; i++)
			{
				/*如果属性名称为tableName,primaryKey时则不拼接到SQL中*/
				if(fields[i].getName().equals("tableName") || fields[i].getName().equals("primaryKey"))
				{
					
				}else
				{
					/*获得对应属性的get方法*/
					Method method = objClass.getDeclaredMethod("get"+FunctionUtils.upInitial(fields[i].getName()));
					sql.append(fields[i].getName());
					sql.append("=");
					
					/*获得对应属性的数据类型,如果是String类型则加单引号*/
					if(fields[i].getType() == java.lang.String.class)
					{
						sql.append("'");
						sql.append(method.invoke(object));
						sql.append("'");
						sql.append(",");
					}else
					{
						sql.append(method.invoke(object));
						sql.append(",");
					}
					
					/*如果此属性为主键*/
					if(fields[i].getName().equals(keyName))
					{
						if(primaryKey.getType().equals("java.lang.String.class"))
						{
							whereSql.append("'");
							whereSql.append(method.invoke(object));
							whereSql.append("'");
						}else
						{
							whereSql.append(method.invoke(object));
						}
					}
				}
			}
			
			/*删除多余的逗号*/
			sql.delete(sql.length()-1, sql.length());
			
			/*执行操作,并返回作用的行数*/
			int count = BaseOperatorDao.delOrSaveOrUpdateData(sql.toString()+whereSql.toString());
			
			if(count == 0)
			{
				System.out.println("请确定数据库中是否由此记录");
			}
			
			System.out.println(sql.toString()+whereSql.toString());
			
		} catch (SecurityException e)
		{
			e.printStackTrace();
		} catch (NoSuchFieldException e)
		{
			e.printStackTrace();
		} catch (IllegalArgumentException e)
		{
			e.printStackTrace();
		} catch (IllegalAccessException e)
		{
			e.printStackTrace();
		} catch (NoSuchMethodException e)
		{
			e.printStackTrace();
		} catch (InvocationTargetException e)
		{
			e.printStackTrace();
		}
	}


以下是用法规则:
1,此方法不适合复合主键
2,实体类的属性名称必须要与数据的字段名一致
3,此方法的对应实体类必须有public static tableName ="XXX" //代表的对应的数据库名
                          public static primaryKey = "XXX" //代表对应的主键名称
  例如:
public class User
{
	/**用户编号*/
	private Integer id;
	
	/** 用户名 */
	private String name;

	/** 用户密码 */
	private String pwd;

	/** 用户音乐盒子 */
	private String music_box;
	
	/**对应数据库名称*/
	public static String tableName = "user";
	
	/**数据对应的主键*/
	public static String primaryKey = "id";

	/**
	 * get,set方法
	 * @return
	 */
	public String getName()
	{
		return name;
	}

	public Integer getId()
	{
		return id;
	}

	public void setId(Integer id)
	{
		this.id = id;
	}

	public void setName(String name)
	{
		this.name = name;
	}

	public String getPwd()
	{
		return pwd;
	}
	
	public void setPwd(String pwd)
	{
		this.pwd = pwd;
	}

	public String getMusic_box()
	{
		return music_box;
	}

	public void setMusic_box(String musicBox)
	{
		music_box = musicBox;
	}
}

哈哈,最后打条广告:本人现在(二流)本科大三,想在暑假出去实习,所投简历石沉大海,希望那位前辈能推荐一下。本人真心热爱编程,QQ:982925115

猜你喜欢

转载自zhong678-yeah-net.iteye.com/blog/1501760