您的位置:首页 > 编程语言 > Java开发

Java反射机制应用:对象关系映射(ORM)

2009-01-20 21:19 399 查看
学过Java的人,应该对SSH不会感到陌生,Struts,Spring,Hibernate这三大企业的主流开发框架,正在给越来越多的Java开发人员使用。但是要知道这些框架底层的实现机制的话,还得再花一点功夫。这些框架底层的实现,其实是使用很多Java反射机制原理。而什么是反射机制呢,在这篇文章里,我就详细说明了,在google,百度一搜很多这方面的资料。

下面,我举个例子,使用Java的机制来实现一个类似于Hibernate的ORM(Object-relational mapping)的数据库访问层的框架。要实现这种基于对象的数据库操作,我们要考虑的问题是:
1. 如何来构建SQL语句来实现CRUD(create, read, update, delete)的操作,也就是我们通常讲的增删改查的操作
2. 如何确定对象中的哪些属性是需要insert或者是update的
3. 如何把对象和底层的数据库表对应起来
如何你把上面这几个问题搞明白的话,要实现一个简单的ORM的框架就不是一件很难的事情了。
假定,现在我们需要对Student这个对象进行数据库增删改的操作,其对应的数据库表是t_student
1. 首先我们来定义一个Student类:
/**
* Copyright (c) 2008 Ivan Lau, www.dongua.com, www.pcschoolchina.com
* All rights reserved
*/
public class Student{
private int id;
private String name;
private String gender;
private float height;
private float weight;
private int age;
private String address;
private String phone;
private String mobile;
private String description;
.....
}


2. 定义生成SQL语句的DaoUtil类
//生成SQL语句的DaoUtil类
public class DaoUtil {
/**
* eg. insert into student(name,age) values(?,?)
* @param vo
* @param paramValues
* @return
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws InvocationTargetException
*/
public static String getInsertSQLFromVO(Object vo, List paramValues)
throws IllegalArgumentException, IllegalAccessException,
InvocationTargetException {
//保存字段的名称
StringBuilder fieldNames = new StringBuilder("(");
//保存参数中的问号 “?”
StringBuilder fieldParams = new StringBuilder(" values(");
Class type = vo.getClass();
//根据对象vo的类型获取改对象中的所有public的方法
Method[] methods = type.getMethods();
for (Method method : methods) {
String methodName = method.getName();
//把get***的方法获取到
if (methodName.startsWith("get")&&
!"getId".equals(methodName)&&
!"getClass".equals(methodName)) {
String fieldName = methodName.substring(3).toLowerCase();
//通过方法调用自己,来获取到对象中的指定的fieldName的属性值。
Object fieldVal = method.invoke(vo, null);
if (fieldVal != null) {
fieldNames.append(fieldName + ",");
fieldParams.append("?,");
//把对象中的属性值加入到paramValues参数List中。
paramValues.add(fieldVal);
}
}
}
fieldNames.deleteCharAt(fieldNames.length() - 1);
fieldParams.deleteCharAt(fieldParams.length() - 1);
//返回的就是类似这样的一个字符串: (name,age) values(?,?),这个时候paramValues也完成了初始化。
return fieldNames.append(")" + fieldParams.toString() + ")").toString();
}
}

3. 定义数据访问类BaseDao
//BaseDao执行以对象作为基础的数据库操作,也就是ORM的一部分。
//DbManager.executeSQL这个函数请看我的之前的14楼的帖子。
public class BaseDao {
protected static String tableName = null;
public void create(Object o) throws Exception {
StringBuffer sql = new StringBuffer("");
List params = new ArrayList();
sql.append("insert into " + this.tableName);
sql.append(DaoUtil.getInsertSQLFromVO(o, params));
System.out.println("sql: " + sql.toString());
try {
DbManager.executeSQL(sql.toString(), params);
} catch (Exception ex) {
throw ex;
}
}
}


4. DbManager类中的定义的executeSQL的执行SQL语句
public static void executeSQL(String sql, List params) throws Exception {
Connection con;
PreparedStatement pstmt;
con = null;
pstmt = null;
boolean abortTransaction = false;
int execute_rs = -1;
try {
con = DbManager.getTransactionConnection();
pstmt = con.prepareStatement(sql);
int i = 0;
for (Object param: params) {
param = param==null? "": param;
pstmt.setObject(i + 1, param);
i++;
}
execute_rs = pstmt.executeUpdate();
} catch (SQLException sqlex) {
abortTransaction = true;
throw sqlex;
} catch (Exception e) {
abortTransaction = true;
throw e;
} finally {
DbManager.closeTransactionConnection(con, abortTransaction);
}
}


5. 最后编写一个测试类

//测试类
public class Test {

public static void main(String[] args){
BaseDao dao = new BaseDao();
StudentVO vo = new StudentVO();
vo.setName("ivan");
vo.setAddress("广州巨匠IT");
vo.setDescription("我爱冬瓜网,爱Java和Python");
try {
dao.create(vo);
} catch (Exception e) {
e.printStackTrace();
}
}

}


版权所有:liuwan@pcschoolchina.com 广州巨匠IT

如果需要完整的源代码的话,请留下你们的Email,我会一一回复!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: