`
H伊方H
  • 浏览: 4572 次
  • 性别: Icon_minigender_1
  • 来自: 揭阳
社区版块
存档分类
最新评论

实现简单的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
分享到:
评论

相关推荐

    类似Hibernate的工具

    标题中的“类似Hibernate的工具”指的是在IT领域中与Hibernate相似的Object-Relational Mapping(ORM)框架。Hibernate是一款流行的Java ORM框架,它允许开发者使用面向对象的方式操作数据库,而无需直接编写SQL语句...

    类似hibernate的jdbc封装

    然而,有些场景下,我们可能并不需要完整的ORM功能,而是寻求一个轻量级的解决方案,这时,对JDBC进行简单的封装就显得非常实用。标题提到的"类似hibernate的jdbc封装"就是这样的一个实践,它试图在不引入庞大框架的...

    ORM hibernate。jar包

    标题提到的"ORM Hibernate .jar包"指的是Hibernate框架的可执行库文件,通常包含了一系列类、接口和实现,供开发者在项目中引用,以实现ORM功能。"hibernate5+jars包"表明这是Hibernate的第五个主要版本,5.2.16....

    spring-orm-hibernate4源码

    Spring也可以通过AOP(Aspect-Oriented Programming)来实现类似的功能。 通过对Spring-ORM-Hibernate4源码的阅读和研究,我们可以更好地理解这两个框架是如何协同工作的,以及如何优化和定制它们以适应特定的项目...

    hibernate-orm-3.3源码

    本文将针对《hibernate-orm-3.3源码》进行深度解析,帮助读者理解其核心设计理念与实现机制。 一、Hibernate概述 Hibernate 是一款开源的 Java 库,它简化了数据库操作,通过将 Java 对象与数据库表之间的映射关系...

    hibernate-orm-3.2.zip

    Hibernate ORM就是实现这一功能的框架,它提供了一种在Java应用中持久化对象的便捷方式。 二、配置文件 在Hibernate 3.2中,主要通过`hibernate.cfg.xml`文件进行配置。这个文件定义了数据库连接参数(如URL、...

    hibernate-framework-orm-4.2.4.Final.zip

    Hibernate作为ORM工具,主要解决了Java应用与数据库之间的数据交互问题,通过将数据库表映射为Java类,实现对象与数据的自动转换。这使得开发者可以使用面向对象的方式来操作数据库,降低了数据库操作的复杂性。 2...

    自定义Orm框架的实现

    3. **会话工厂(SessionFactory)**:类似Hibernate的SessionFactory,负责创建Session对象,Session是对数据库的一次会话,可以进行CRUD操作。 4. **Session接口**:设计Session接口,提供保存、更新、删除和查询...

    [反射机制]简单实现ORM

    在本案例中,"简单实现ORM"是指通过反射机制来实现对象关系映射(Object-Relational Mapping),这是一种将数据库中的数据与Java对象之间建立映射关系的技术,使得开发者可以更方便地操作数据库。 ORM的主要目的是...

    看我山寨版 hibernate 简单实现 一

    这篇文章的主题是作者尝试模仿 Hibernate 框架的功能,创建一个简单的实现。Hibernate 是一个流行的关系对象映射(ORM)框架,它允许 Java 开发人员将数据库操作与对象模型相结合,极大地简化了数据访问层的开发工作...

    hibernate基本功能

    本篇文章主要介绍利用Hibernate框架来实现基本的功能操作,包括登录验证、查询、增加、修改以及删除等常用操作。 #### 二、知识点详解 ##### 1. 登录验证功能实现 登录验证是许多应用中的一个常见需求。在`...

    Hibernate ORM 新特性之 Service(Registry).

    在探讨Hibernate ORM的新特性——Service Registry之前,我们首先要理解Hibernate ORM的基本概念。Hibernate是一个流行的开源对象关系...开发者在升级到新版本时,应适应这一变化,以便更好地利用Hibernate ORM的功能。

    hibernate_orm-master

    《Hibernate ORM 深度解析与实践指南》 Hibernate ORM 是一个开源的Java对象关系映射框架,它为开发者提供了一种在Java应用程序中管理关系数据库的便捷方式。本资料包"hibernate_orm-master.zip"包含了"hibernate-...

    spring mvc+hibernate实现的用户管理系统

    Spring MVC和Hibernate是JavaEE开发中非常流行的框架,分别用于实现MVC设计模式和提供ORM(对象关系映射)功能。整合这两种技术可以提高开发效率,增强系统的可维护性和扩展性。 首先,Spring MVC是一个强大的MVC...

    hibernate基础jar包

    7. HQL和Criteria API:Hibernate Query Language(HQL)是Hibernate特有的面向对象的查询语言,类似于SQL,但操作的是对象而非表格。Criteria API是一种类型安全的API,可以动态构建查询,避免SQL注入风险。 8. ...

    jap+hibernate4实现

    在早期版本中,人们普遍使用Hibernate 3,它是一个功能强大的ORM框架,但在Java社区中,随着JPA 2的引入,越来越多的开发者转向了这个标准的持久化API。本教程将深入探讨如何将JPA与Hibernate 4集成,以利用其更新的...

    SpringMVC+Hibernate+Oracle 实现登录、注册、增删改查功能!

    注册功能类似,但涉及到新用户的创建,需要使用Hibernate的`save()`或`persist()`方法将新用户信息存入数据库。 增删改查(CRUD)操作是数据管理的核心。在Hibernate中,通过Session对象可以直接操作实体,比如`...

    spring4.2+hibernate5环境开发全部jar包

    Spring是一个全面的后端应用程序框架,提供了依赖注入、AOP(面向切面编程)、数据访问、事务管理等多种功能,而Hibernate则是一个强大的对象关系映射(ORM)工具,简化了数据库操作。下面将详细解释这两个框架以及...

    Hibernate个人博客设计与实现

    在本项目"Hibernate个人博客设计与实现"中,我们主要关注的是如何利用Java持久化框架Hibernate来构建一个功能完备的个人博客系统。Hibernate是一个强大的ORM(对象关系映射)工具,它极大地简化了数据库操作,使得...

    hibernate资源包详解

    4. **odmg.jar**:ODMG(Object-Database Mapping Group)提供了一套ORM规范,Hibernate实现了这一规范,使得ORM操作更加标准和统一。 5. **commons-collections.jar**:Apache Commons Collections提供了许多Java...

Global site tag (gtag.js) - Google Analytics