我的一点看法:
1.我觉得formbean的作用是将页面表单对象化,这带来的好处是显而易见的,比如程序员因此就可以使用Set
或者Get等面向对象的方法存取网页上的数据了.所以formbean表达的应该只是页面信息,与后边的to之类是没有关系的,比如formbean也许只映射 了一个to的数据,也许也映射了一个to的list,不知道说的对不对.所以因为它的不确定性来说,form与to的映射只有手工来完成.但是,根据一些特殊的 条件或是特殊的约束,比如在类似的"简单应用"中,我们规定一个form与一个to相映射,并且相对应的属性name相同的话,就可以用一些类反射机制或是ja va.beans里边的东西来写一个自动映射的static方法:
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import com.arcturus.arctoa.util.*;
public class Util {
public static void copyProperties(Object desObj, Object resObj) {
PropertyDescriptor descriptor = null;
try {
BeanInfo beanInfo =
Introspector.getBeanInfo(resObj.getClass());
PropertyDescriptor[] descriptors
= beanInfo.getPropertyDescriptors();
String[] names = new String[descriptors.length];
int i = 0;
for (/**/; i < names.length; i++) {
String name = descriptors[i].getName();
Class type = descriptors[i].getPropertyType();
if (descriptors[i].getReadMethod() != null) {
Object value
=
descriptors[i].getReadMethod().invoke(resObj);
try {
descriptor
= new PropertyDescriptor(name,
desObj.getClass());
} catch (IntrospectionException ex) {
continue;
}
try {
if
(!descriptor.getPropertyType().isPrimitive()) {
Object obj
= convertValue(value,
descriptor.getPropertyType(),
desObj);
descriptor.getWriteMethod()
.invoke(desObj, new Object[] { obj });
}
} catch (Exception ex) {
System.out
.println("the function name is ----->"
+ name);
ex.printStackTrace();
}
}
}
} catch (Exception e) {
System.out.println(descriptor.getName());
System.out.println(descriptor.getPropertyType().getName());
e.printStackTrace();
}
}
private static Object convertValue(Object resValue, Class desType,
Object desObj) {
if (resValue == null)
return resValue;
if
(resValue.getClass().getName().equalsIgnoreCase(desType.getName()))
return resValue;
if (resValue.getClass().getSuperclass().getName()
.equalsIgnoreCase(desType.getName()))
return resValue;
if ((resValue instanceof Boolean || resValue instanceof Integer
|| resValue instanceof Long || resValue instanceof
Float
|| resValue instanceof Double)
&&
desType.getName().equalsIgnoreCase("java.lang.String"))
return resValue.toString();
if (desType.getName().equalsIgnoreCase("java.lang.Boolean")
&& resValue instanceof String) {
Boolean var_boolean;
try {
var_boolean = new Boolean((String) resValue);
} catch (Exception ex) {
return null;
}
return var_boolean;
}
if (desType.getName().equalsIgnoreCase("java.lang.Integer")
&& resValue instanceof String) {
Integer integer;
try {
integer = new Integer((String) resValue);
} catch (NumberFormatException ex) {
return null;
}
return integer;
}
if (desType.getName().equalsIgnoreCase("java.lang.Long")
&& resValue instanceof String) {
Long var_long;
try {
var_long = new Long((String) resValue);
} catch (NumberFormatException ex) {
return null;
}
return var_long;
}
if (desType.getName().equalsIgnoreCase("java.lang.Float")
&& resValue instanceof String) {
Float var_float;
try {
var_float = new Float((String) resValue);
} catch (NumberFormatException ex) {
return null;
}
return var_float;
}
if (desType.getName().equalsIgnoreCase("java.lang.Double")
&& resValue instanceof String) {
Double var_double;
try {
var_double = new Double((String) resValue);
} catch (NumberFormatException ex) {
return null;
}
return var_double;
}
return null;
}
private Util() {
}
}
不知道这个Util是不是和Apach-e的commons工具包的BeanUtil相同,写在这里大家有兴趣可以研究一下,可能存在关于陈哥说的重载问题,不 过我看了java.lang.class中的getMethod(String
name, Class...
parameterTypes)方法可以返回一个确定的参数类型的方法,配合Field根据Field产生getMethod方法中的name参数,应该可以解 决这个问题,不过要注意,field一定要记得setAccessible(true).说的远了^^完成这个工具后,只要在别的类中import它,然后就可 以用:
Util.copyProperties(formBean, toBean);
Util.copyProperties(toBean, formBean);
来自动进行映射了.如果把这个加入到这个简单框架中,不知道可行不可行.
2有个问题,刚才看那个OA的代码才弄明白,它也是通过类反射机制来实现数据库操作的.比如DBProcessor中的static方法query(Strin g
sql,String
className)中根据传入的sql得到ResultSet,再通过ResultSetMetaData
rsmd =
rs.getMetaData();得到列信息,然后循环自动创建并付值类名为className的对象,以ArrayList或数组的方式返回,大概流程转来 网上一段程序:
public ArrayList query(String sql,String className){
ArrayList paraList=new ArrayList();
//传入的sql得到ResultSet
try{
if (conn == null){
Connection();
}
PreparedStatement stmt = conn.prepareStatement(sql);
ResultSet rs = stmt.executeQuery();
String recordValue="";
Object c1=null;
paraList=new ArrayList();
//再通过ResultSetMetaData rsmd =
rs.getMetaData();得到列信息
ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();
//循环自动创建并付值类名为className的对象,以ArrayList或数组的方式返回
//循环rs每一行
while (rs.next()){
//创建一个类名为className的对象
c1=Class.forName(className).newInstance();
//循环每一行中的每一列
for (int i=1; i<=columnCount; i++) {
if(rs.getString(rsmd.getColumnName(i))!=null){
recordValue=rs.getString(rsmd.getColumnName(i));
}else{
recordValue="";
}
//得到类中与表当前列名相同的属性的set方法
Method
m=c1.getClass().getMethod(getSetMethodName(rsmd.getColumnName(i))
,new
Class[]{recordValue.getClass()});
//执行set方法,将表当前行当前列下的数据set进对象中
m.invoke (c1, new Object[]{recordValue});
}
paraList.add(c1);
}
}catch(SQLException ex){
}catch(ClassNotFoundException e){
}catch(NoSuchMethodException e) {
}catch(InvocationTargetException e){
}catch (IllegalAccessException e){
}catch(InstantiationException e){
} finaly{
closeConnection();
return paraList;
}
}
这样就不用为每个表建一个dao了都,因为在这种简单的对表的CRUD中,完全可以将FORMBEAN建的与数据库中的字段对应,这样得到的所有不用的form Bean对象就可以直接或间接的被query(或是insert,update,delete)方法调用,完成数据库操作:
ArrayList forms=
query(sql,formBean.getClass());//先执行sql,然后循环创建formBean对象,利用类反射机制为每个formBean 付值返回
insert((ActionForm)formBean);//根据类反射机制找出formBean的所有属性和对应的值,拼成sql执行
update((ActionForm)formBean);//同上
del((ActionForm)formBean);//同上
不知道表达是否正确清楚.这样只有一个类的几个静态方法就可以完成一堆DAO的任务,当然是在这种简单的对表的CRUD中,完全可以将每一个formBean的 属性名称建的与数据库中一个表字段名称完全对应的情况下.而这种情况应该在本文讨论的语境范围内,不知道这种方式是否可行?