之前, 在做web 个人blog项目的时候,
数据库那里设置了三个表 ---- userinfo, article, comment
然后,在项目里写了个pojo包, dao包.
里面 分别都有三个表的 对应的 实现类 和 操作类 ,
这样, 即使是只写 基本的 CRUD操作. 也都要写3遍.
代码量,复杂程度 可想而知 ...
现在, 利用 java 灵活的反射功能.
可以 很灵活的 通过反射 判断一个对象的类
从而 实现 智能分析的功能.
举个例子, 通过一个例子 比较一下:
任务: 往数据库里 分别添加一个 user对象, 一个article对象, 一个comment对象
之前:
- 调用 user 的dao类 的save方法. eg: userDao.save(user);
- 调用 article 的dao类 的save方法. eg: articleDao.save(article);
- 调用comment 的dao类 的save方法. eg: commentDao.save(comment);
现在:
- save(user);
- save(article);
- save(comment);
是不是很省事???
来看看具体的代码 是怎么实现的吧...
先大致的介绍一下这个东东的基本功能....
1. 增加对象. .
/**
* 保存一个对象的 方法.
* @param obj: 要保存的对象
*/
public static boolean save (Object obj){}
sql = insert into obj.类名 (属性1,属性2,...) values (值1,值2, ...) ;
2. 删除对象..
/**
* 删除一个对象的方法
* @param id: 要删除的数据的ID,
* @param c : 要删除的数据的类型.
*/
public static boolean delete (int id , Class c){}
sql = delete from 类名 where id= id;
3. 修改对象的属性值
/**
* 修改一个对象的信息的方法
* @param obj: 传入修改后的对象
*/
public static boolean modify (Object obj){}
sql = update obj.类名 set 属性1=值1,属性2=值2,... where id = obj.getId;
4. 查找---某一类型的全部对象
/**
* 查找某一个类型的所有对象. select * from 表名;
*
* @return : 对象的队列
*/
public static List selectAll(Class c) {}
sql = select * from 类名;
5. 查找--- 根据某些属性 模糊查找
/**
* 根据一个模板来查找对象 可以理解成为多条件查找. eg: 查找 age=20, name="Lilei" 的用户
*
* @param obj
*/
public static List selectBySample(Object obj) {}
sql = select * from 类名 where 属性1 = 值1 and 属性2 like 值2 ...;
(int型 就用等号连接, string型 则模糊查找 用like 连接)
6. 查找--- 根据id 来查找
/**
* 通过唯一的 主键 id 查找对象的方法
*
* @param id: id
* @param c : 要查找的类型
* @return : 返回对象
*/
public static Object selectById(int id, Class c) {}
sql = select * from 类名 where id = id;
目前只写了这么多功能...
相信多花点心思下去, 可以写得更好的...
大家可能注意到, 上面的每一个功能下面 我都添加了个 sql 的注释..
因为, 在现在看来.
下面的代码, 所干的事情, 就是 :
- 拼凑一条 符合操作要求的 sql ;
- 执行sql 语句;
- 返回结果;
- 对结果 进行处理 --- (对于selec 语句: 把得到的属性值 赋值给一个对象, 返回这个对象, 或者这个对象队列..)
其中 写出 一句 正确的 sql 语句是 很关键的一步...
具体实现. 就看看下面的代码吧...
package orm;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.Date;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
* 山寨hibernate的实现. 实现ORM 功能
*
* @author 小奇
*
*/
public class HibernateORM {
/**
* 保存一个对象的 方法.
*
* @param obj
* : 要保存的对象
*/
public static boolean save(Object obj) {
// 1.拼凑一条 保存的sql语句 insert into 类名 (属性1,属性2,...) values (值1,值2, ...) ;
String sql = "insert into ";
// 得到对象的类
Class c = obj.getClass();
// 得到类名 也就是表名
String cName = c.getName();
sql += cName.substring(cName.lastIndexOf(".") + 1, cName.length());
// 得到类中的所有方法的队列
java.lang.reflect.Method[] methods = c.getMethods();
List<Method> gets = new ArrayList<Method>();
for (Method m : methods) {
String s = m.getName();
// 判断是否为 get 方法 而且 不是getClass 方法
if (s.startsWith("get") && !s.equals("getClass")) {
try {
// int类型的默认值是 0; 所以必须去除这种 默认值的..
if ((m.invoke(obj, null) != null)
&& !m.invoke(obj, null).equals(0)) {
gets.add(m);
System.out.println("------>方法名:" + s);
}
} catch (IllegalArgumentException e1) {
e1.printStackTrace();
} catch (IllegalAccessException e1) {
e1.printStackTrace();
} catch (InvocationTargetException e1) {
e1.printStackTrace();
}
}
}
String properties = "(";
String values = "(";
for (int i = 0; i < gets.size(); i++) {
Method m = gets.get(i);
// 先判断属性值 是否为null 如果为null 则没必要继续写入语句
try {
String s = m.getName();
// 得到属性名 即get后面的字符串
String fName = s.substring(3, s.length());
if (i != gets.size() - 1) {
properties += fName + " , ";
} else
properties += fName + ") ";
// 执行get方法
// 判断get方法的返回类型
Class re = m.getReturnType();
String value;
if (re.getName().equals("int")) { // 如果是int 类型, 则直接添加就行.
value = ((Integer) m.invoke(obj, null)).toString();
if (i != gets.size() - 1) {
values += value + ",";
} else
values += value + ")";
} else if (re.getName().equals("String")) { // 如果是String类型
// 则要记得加单引号 ' '
value = (String) m.invoke(obj, null);
if (i != gets.size() - 1) {
values += "'" + value + "' ,";
} else
values += "'" + value + "' )";
} else {
System.out.println("未知的数据类型... 暂时不支持");
}
} catch (IllegalArgumentException e1) {
e1.printStackTrace();
} catch (IllegalAccessException e1) {
e1.printStackTrace();
} catch (InvocationTargetException e1) {
e1.printStackTrace();
}
}
sql += properties + "values" + values;
System.out.println("得到的sql语句是: " + sql);
// 2. 连接数据库
Connection conn = dbConn.DBUtil.getConn();
// 3. 执行sql 语句
try {
java.sql.Statement stmt = conn.createStatement();
int t = stmt.executeUpdate(sql);
if (t == 1) {
System.out.println("保存成功!");
return true;
} else {
System.out.println("删除失败!");
}
} catch (SQLException e) {
e.printStackTrace();
}
// 4. 返回结果
return false;
}
/**
* 删除一个对象的方法
*/
public static boolean delete(int id, Class c) {
// 1.拼凑一条 保存的sql语句 delete from 类名 where id = id ;
String sql = "delete from ";
// 得到类名 也就是表名
String cName = c.getName();
sql += cName.substring(cName.lastIndexOf(".") + 1, cName.length());
sql += " where id = " + id;
System.out.println("得到的sql语句是: " + sql);
// 2. 连接数据库
Connection conn = dbConn.DBUtil.getConn();
// 3. 执行sql 语句
try {
java.sql.Statement stmt = conn.createStatement();
int i = stmt.executeUpdate(sql);
if (i == 1) {
System.out.println("删除成功!");
return true;
} else {
System.out.println("删除失败!");
}
} catch (SQLException e) {
e.printStackTrace();
}
// 4. 返回结果
return false;
}
/**
* 修改一个对象的信息的方法
*/
public static boolean modify(Object obj) {
// 1.拼凑一条 保存的sql语句
String sql = "update ";
int id = 0;
// 得到对象的类
Class c = obj.getClass();
// 得到类名 也就是表名
String cName = c.getName();
sql += cName.substring(cName.lastIndexOf(".") + 1, cName.length());
sql += " set ";
// 得到类中的所有方法的队列
java.lang.reflect.Method[] methods = c.getMethods();
List<Method> gets = new ArrayList<Method>();
for (Method m : methods) {
String s = m.getName();
System.out.println("--->方法名:" + s);
// 判断是否为 get 方法 而且 不是getClass 方法
if (s.startsWith("get") && !s.equals("getClass")) {
try {
// 先判断属性值 是否为null或者初始值"0" , 如果是 , 则没必要继续写入语句
if (m.invoke(obj, null) != null
&& !m.invoke(obj, null).equals(0)) {
gets.add(m);
System.out.println("------>方法名:" + s);
}
} catch (IllegalArgumentException e1) {
e1.printStackTrace();
} catch (IllegalAccessException e1) {
e1.printStackTrace();
} catch (InvocationTargetException e1) {
e1.printStackTrace();
}
}
}
for (int i = 0; i < gets.size(); i++) {
Method m = gets.get(i);
try {
// 如果是 getId 方法. 则得到id.
if (m.getName().equalsIgnoreCase("getId")) {
id = (Integer) m.invoke(obj, null);
} else {
String s = m.getName();
// 得到属性名 即get后面的字符串
String fName = s.substring(3, s.length());
sql += fName + "=";
// 执行get方法
// 判断get方法的返回类型
Class re = m.getReturnType();
String value;
if (re.getName().equals("int")) { // 如果是int 类型, 则直接添加就行.
value = ((Integer) m.invoke(obj, null)).toString();
if (i != gets.size() - 1) {
sql += value + ",";
} else
sql += value;
} else { // 如果是String类型 则要记得加单引号 ' '
value = (String) m.invoke(obj, null).toString();
if (i != gets.size() - 1) {
sql += "'" + value + "' ,";
} else
sql += "'" + value + "'";
}
}
} catch (IllegalArgumentException e1) {
e1.printStackTrace();
} catch (IllegalAccessException e1) {
e1.printStackTrace();
} catch (InvocationTargetException e1) {
e1.printStackTrace();
}
}
sql += " where id = " + id;
System.out.println("得到的sql语句是: " + sql);
// 2. 连接数据库
Connection conn = dbConn.DBUtil.getConn();
// 3. 执行sql 语句
try {
java.sql.Statement stmt = conn.createStatement();
int i = stmt.executeUpdate(sql);
if (i == 1) {
System.out.println("更改信息成功!");
return true;
} else {
System.out.println("更改信息失败!");
}
} catch (SQLException e) {
e.printStackTrace();
}
// 4. 返回结果
return false;
}
/**
* 根据一个模板来查找对象 可以理解成为多条件查找. eg: 查找 age=20, name="Lilei" 的用户
*
* @param obj
*/
public static List selectBySample(Object obj) {
// 即将返回的 队列....
List list = new ArrayList();
String sql = "select * from ";
Class c = obj.getClass();
String cName = c.getName();
sql += cName.substring(cName.lastIndexOf(".") + 1, cName.length())
+ " where ";
// 得到类中的所有方法的队列
java.lang.reflect.Method[] methods = c.getMethods();
List<Method> gets = new ArrayList<Method>();
List<Method> sets = new ArrayList<Method>();
for (Method m : methods) {
String s = m.getName();
if (s.startsWith("set")) {
// 添加 set 方法进入队列
sets.add(m);
System.out.println("--- >set方法名:" + s);
String field = s.substring(3);
for (Method sm : methods) {
if (sm.getName().equals("get" + field)) {
// 添加 get 方法 进入队列
gets.add(sm);
System.out.println("------>get方法名:" + sm.getName());
}
}
}
}
for (int i = 0; i < gets.size(); i++) {
Method get = gets.get(i);
try {
// 先判断 sample里面的非初始化的值
if (get.invoke(obj, null) != null
&& !get.invoke(obj, null).equals(0)) {
String name = get.getName();
// 得到属性名 即get后面的字符串
String fName = name.substring(3, name.length());
// 执行get方法
// 判断get方法的返回类型
Class re = get.getReturnType();
String value;
if (re.getName().equals("int")) { // 如果是int 类型, 则直接添加就行.
value = ((Integer) get.invoke(obj, null)).toString();
sql += fName + "="; // 如果是 int 型, 则用"=" 连接
sql += value + " and ";
} else { // 如果是String类型 则要记得加单引号 ' '
value = (String) get.invoke(obj, null).toString();
sql += fName + " like "; // 如果是 string 型, 则用"=" 连接
sql += "'%" + value + "%' and ";
}
}
} catch (IllegalArgumentException e1) {
e1.printStackTrace();
} catch (IllegalAccessException e1) {
e1.printStackTrace();
} catch (InvocationTargetException e1) {
e1.printStackTrace();
}
}
// 输出sql语句 测试 记得去掉最后的 "and" 三个字符
sql = sql.substring(0, sql.length() - 4);
System.out.println("得到的sql 语句是: " + sql);
// 执行sql 语句
Connection conn = dbConn.DBUtil.getConn();
try {
java.sql.Statement stmt = conn.createStatement();
java.sql.ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
// 创建这个类型的新对象
Object o = c.newInstance();
// 给这个对象 设置属性. 赋值
for (int i = 0; i < sets.size(); i++) {
Method set = sets.get(i);
Method getM = gets.get(i);
// 得到set 方法名字 eg: setAge
String mName = set.getName();
System.out.println("得到的set 方法是: " + mName);
// 得到属性名字 eg: Age --> age
String fName = mName.substring(3, 4).toLowerCase()
+ mName.substring(4);
Class re = getM.getReturnType();
System.out.println("set方法返回类型是: " + re.getName());
if (re.getName().equals("int")) { // 如果是int 类型
int param = rs.getInt(fName);
System.out.println(" rs 得到的是: " + param);
set.invoke(o, param);
} else if (re.getName().equals("java.lang.String")) { // 如果是String类型
String param = rs.getString(fName);
if (param != null) { // 如果rs得到的不是null
set.invoke(o, param);
}
} else if (re.getName().equals("java.sql.Date")) {
Date param = rs.getDate(fName);
if (param != null) { // 如果rs得到的不是null
set.invoke(o, param);
}
}
}
// 把对象加入 队列中...
list.add(o);
}
} catch (Exception e) {
e.printStackTrace();
}
return list;
}
/**
* 查找某一个类型的所有对象. select * from 表名;
*
* @return : 对象的队列
*/
public static List selectAll(Class c) {
// 即将返回的 队列....
List list = new ArrayList();
String sql = "select * from ";
String cName = c.getName();
sql += cName.substring(cName.lastIndexOf(".") + 1);
// 得到类中的所有方法的队列
java.lang.reflect.Method[] methods = c.getMethods();
List<Method> gets = new ArrayList<Method>();
List<Method> sets = new ArrayList<Method>();
for (Method m : methods) {
String s = m.getName();
if (s.startsWith("set")) {
// 添加 set 方法进入队列
sets.add(m);
System.out.println("--- >set方法名:" + s);
String field = s.substring(3);
for (Method sm : methods) {
if (sm.getName().equals("get" + field)) {
// 添加 get 方法 进入队列
gets.add(sm);
System.out.println("------>get方法名:" + sm.getName());
}
}
}
}
// 输出sql语句 测试
System.out.println("得到的sql 语句是: " + sql);
// 执行sql 语句
Connection conn = dbConn.DBUtil.getConn();
try {
java.sql.Statement stmt = conn.createStatement();
java.sql.ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
// 创建这个类型的新对象
Object o = c.newInstance();
// 给这个对象 设置属性. 赋值
for (int i = 0; i < sets.size(); i++) {
Method set = sets.get(i);
Method getM = gets.get(i);
// 得到set 方法名字 eg: setAge
String mName = set.getName();
System.out.println("得到的set 方法是: " + mName);
// 得到属性名字 eg: Age --> age
String fName = mName.substring(3, 4).toLowerCase()
+ mName.substring(4);
Class re = getM.getReturnType();
System.out.println("set方法返回类型是: " + re.getName());
if (re.getName().equals("int")) { // 如果是int 类型
int param = rs.getInt(fName);
System.out.println(" rs 得到的是: " + param);
set.invoke(o, param);
} else if (re.getName().equals("java.lang.String")) { // 如果是String类型
String param = rs.getString(fName);
if (param != null) { // 如果rs得到的不是null
set.invoke(o, param);
}
} else if (re.getName().equals("java.sql.Date")) {
Date param = rs.getDate(fName);
if (param != null) { // 如果rs得到的不是null
set.invoke(o, param);
}
}
}
// 把对象加入 队列中...
list.add(o);
}
} catch (IllegalArgumentException e1) {
e1.printStackTrace();
} catch (IllegalAccessException e1) {
e1.printStackTrace();
} catch (InvocationTargetException e1) {
e1.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
return list;
}
/**
* 通过唯一的 主键 id 查找对象的方法
*
* @param id
* : id
* @param c
* : 要查找的类型
* @return : 返回对象
*/
public static Object selectById(int id, Class c) {
String sql = "select * from ";
String cName = c.getName();
sql += cName.substring(cName.lastIndexOf(".") + 1) + " where id = "
+ id;
// 得到类中的所有方法的队列
java.lang.reflect.Method[] methods = c.getMethods();
List<Method> gets = new ArrayList<Method>();
List<Method> sets = new ArrayList<Method>();
for (Method m : methods) {
String s = m.getName();
if (s.startsWith("set")) {
// 添加 set 方法进入队列
sets.add(m);
System.out.println("--- >set方法名:" + s);
String field = s.substring(3);
for (Method sm : methods) {
if (sm.getName().equals("get" + field)) {
// 添加 get 方法 进入队列
gets.add(sm);
System.out.println("------>get方法名:" + sm.getName());
}
}
}
}
// 输出sql语句 测试
System.out.println("得到的sql 语句是: " + sql);
// 执行sql 语句
Connection conn = dbConn.DBUtil.getConn();
try {
java.sql.Statement stmt = conn.createStatement();
java.sql.ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
// 创建这个类型的新对象
Object o = c.newInstance();
// 给这个对象 设置属性. 赋值
for (int i = 0; i < sets.size(); i++) {
Method set = sets.get(i);
Method getM = gets.get(i);
// 得到set 方法名字 eg: setAge
String mName = set.getName();
System.out.println("得到的set 方法是: " + mName);
// 得到属性名字 eg: Age --> age
String fName = mName.substring(3, 4).toLowerCase()
+ mName.substring(4);
Class re = getM.getReturnType();
System.out.println("set方法返回类型是: " + re.getName());
if (re.getName().equals("int")) { // 如果是int 类型
int param = rs.getInt(fName);
System.out.println(" rs 得到的是: " + param);
set.invoke(o, param);
} else if (re.getName().equals("java.lang.String")) { // 如果是String类型
String param = rs.getString(fName);
if (param != null) { // 如果rs得到的不是null
set.invoke(o, param);
}
} else if (re.getName().equals("java.sql.Date")) {
Date param = rs.getDate(fName);
if (param != null) { // 如果rs得到的不是null
set.invoke(o, param);
}
}
}
return o;
}
} catch (IllegalArgumentException e1) {
e1.printStackTrace();
} catch (IllegalAccessException e1) {
e1.printStackTrace();
} catch (InvocationTargetException e1) {
e1.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
return null;
}
}