您的位置:首页 > 其它

反射机制简化Dao层开发

2017-09-17 09:14 435 查看
本文参考了:Java反射机制在DAO层的应用实例

所完成的功能是:由于Dao层有很多代码都是重复的,故想要使用几个类封装一下这个过程。

结果实现:完成Dao层的基础功能,更多的功能可以继续封装,也可以由开发者自己实现。代码在下边,需要的请自取。

基本思路是:

首先创建一个连接池存储数据库链接,再使用一个类 DataSourceDeal 封装了处理数据库的过程,完成包括取数据库连接,传sql语句,执行sql语句,处理结果集,关闭PreStatement和ResultSet,回收数据库连接等一系列动作。在处理除了select操作外其他操作都可以直接传入sql语句,然后执行就可以获得操作结果。需要处理select操作时,也仅仅只需重写getObjectFromResult()方法。最后使用一个类 DaoUtil 使用反射机制封装了将Entity转变成执行sql的过程,也就是说仅仅调用DaoUtil中的方法,提供一个Entity实例参数就可以完成数据库的处理了。 是不是很简单?

简单是有代价的,其实也不算代价,只是将一些编写数据库的常用的行为规范化起来而已。

1:Entity的成员变量中必须有一个标识号,名字必须以id结尾,而且不能只是id。

2:Entity中只能有一个以Id结尾的成员变量。

3:Entity中的成员变量由至少两个单词组成,单词用驼峰命名法。

4:数据库中字段命名和Entity一样。

主要部分代码(仅展示部分代码一部分完整版可去下方下载):

/**
*这部分代码主要功能是向数据库中插入一个bean对象
*
*/
// 完成对象的插入
public static Object insertObject(Object obj) {
StringBuilder sb = new StringBuilder("insert into ");
// 获取表名
Class<?> c = obj.getClass();
// 添加到sql语句中
sb.append(getTableNameFromClass(c));
// 获取所有的Field和Method
Method[] methods = c.getDeclaredMethods();
// 存放表名和值的容器
List<String> tableNames = new ArrayList<String>();
final List tableValues = new ArrayList();
// 填充容器
for (Method m : methods) {
String mName = m.getName();
if (mName.startsWith("get") && !mName.startsWith("getClass")) {
Object value = null;
try {
value = m.invoke(obj, null);
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
if(value == null)continue;
tableValues.add(value);
tableNames.add(getFieldFromMethod(mName));
}
}

// 填充sql语句的字段部分
for (int i = 0; i < tableNames.size(); i++) {
if (i == 0) {
sb.append("(");
sb.append(tableNames.get(i));
} else if (i == tableNames.size() - 1) {
sb.append(",");
sb.append(tableNames.get(i));
sb.append(")");
} else {
sb.append(",");
sb.append(tableNames.get(i));
}
}
sb.append(" values(");
// 填充sql语句的值部分
for (int i = 0; i < tableNames.size(); i++) {
sb.append('?');
if (i != tableNames.size() - 1)
sb.append(',');
}
sb.append(")");
// 已经完成sql语句的形成,下边创建处理对象
DataSourceDeal deal = new DataSourceDeal(sb.toString()) {

@Override
public Object getObjectFromResultSet(PreparedStatement ps,
ResultSet rs) {
try {
for (int i = 0; i < tableValues.size(); i++) {
dealValue(ps, i + 1, tableValues.get(i));
}
return ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
return -1;
}
};
// 执行sql语句
Object o = null;
try {
o = deal.doDeal();
} catch (SQLException e) {
e.printStackTrace();
}
System.out.println("返回信息:" + o);
return o;
}
/**
* 根据 value值的类型将 value 放到PreparedStatement指定位置中
*
* @param ps
* @param index
*            在sql语句中?的位置
* @param value
*            表中字段值
*/
private static void dealValue(PreparedStatement ps, int index, Object value)
throws SQLException {
if (value instanceof String) {
ps.setString(index, (String) value);
} else if (value instanceof Date) {
try {
ps.setDate(index, new java.sql.Date(((Date) value).getTime()));
} catch (SQLException e) {
e.printStackTrace();
ps.setTimestamp(index,
new java.sql.Timestamp(((Date) value).getTime()));
}
} else if (value instanceof Integer) {
ps.setInt(index, (Integer) value);
} else if (value instanceof Long) {
ps.setLong(index, (Long) value);
} else if (value instanceof Double) {
ps.setDouble(index, (Double) value);
}

}
/**
* 从提供方法的名字获取到与之匹配的数据库字段名 ---即从set,get方法名称获取到数据库中字段名字
*
* @param MethodName
* @return
*/
private static String getFieldFromMethod(String MethodName) {
String selectId = MethodName.substring(3);
return selectId;
}

/**
* 从Bean类名名获取到表名
*
* @param c
* @return
*/
private static String getTableNameFromClass(Class c) {
String cName = c.getName();
return cName.substring(cName.lastIndexOf(".") + 1);
}


再看看调用的代码:

@Test
public void test_insertObjects(){
Person person = new Person();
person.setPersonId(102L);
//      person.setPersonBirthday(new Date());
person.setPersonName("zff罚单");
person.setPersonPassword("1945sdf");
DaoUtil.insertObject(person);
}


是不是很简单。 所有的Bean都可以按照这个方式插入数据库

文件和例子已上传,其中有例子:

http://download.csdn.net/download/zf_1024/9982492
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: