- 抽象类和泛型和反射在框架中的应用
抽象类的作用:抽取公共的方法,达到方法的公用。
泛型的作用:不固定具体的返回类型,达到返回动态的参数。
反射的作用:根据传入的类型动态创建对象,并反射set查询到的值,达到动态设置参数。
BaseDao类
public abstract class BaseDao<T> {
public Class entityclass;
public BaseDao(Class<T> entityclass) {
this.entityclass = entityclass;
}
/**
* 查询所有
*/
public List<T> findByAll() throws ClassNotFoundException, SQLException {
try {
String className = entityclass.getSimpleName();
String sql = "select * from " + className;
Statement stat = null;
ResultSet rs = null;
DBHelper instance = DBHelper.getInstance();
Connection conn = instance.getConnection(); //得到数据库连接
List<T> list = new ArrayList<T>();
try {
GetTypeUtil getTypeUtil = new GetTypeUtil();
stat = conn.createStatement();
rs = stat.executeQuery(sql); //执行sql语句
JSONArray array = new JSONArray();
while (rs.next()) {
ResultSetMetaData metaData = rs.getMetaData();
//传result和JsonObject
JSONObject obj = getTypeUtil.getType(rs, metaData);
array.add(obj); //把jsonobject添加到jsonArray中
}
Class<?> clazz = Class.forName(entityclass.getCanonicalName());
list = (List<T>) JSON.parseArray(array.toJSONString(), clazz);
} catch (SQLException e) {
e.printStackTrace();
} finally {
instance.free(rs, stat, conn);
}
return list;
} catch (SecurityException e1) {
e1.printStackTrace();
}
return null;
}
}
ServiceImpl类
public class AdminServiceImpl extends BaseDao<Admin> implements AdminService {
public AdminServiceImpl(Class<Admin> entityclass) {
super(entityclass);
}
}
调用Service层
List<Admin> list = adminserviceimpl.findByAll();
思考:假如我现在需要搭一个框架,我要如何把这些技术的好处应用到框架中。
2、反射动态拼接sql,获取对象上自定义注解上的表名
反射作用:反射获取入参对象的参数值,反射获取入参对象的参数名,动态拼接sql
/**
* 新增
*
* @throws Exception 目前只支持Interger 和 String 类型的字段
*/
public boolean add(Object entityclass) throws Exception {
Statement stat = null;
ResultSet rs = null;
DBHelper instance = DBHelper.getInstance();
Connection conn = instance.getConnection();
try {
String values = "";
//获取传入的实体类的类名
String className = entityclass.getClass().getSimpleName();
Field[] declaredFields = entityclass.getClass().getDeclaredFields();
for (int j = 0; j < declaredFields.length; j++) {
if (!declaredFields[j].getName().equals("serialVersionUID")) {
if (j != declaredFields.length - 1) {
//自动拼接sql
values += "?" + ",";
} else {
values += "?";
}
}
}
//原型是 insert into "+className+" values(?,?,?,?....)
String sql = "insert into " + className + " values(" + values + ")";
//执行sql语句
PreparedStatement param = conn.prepareStatement(sql);
for (int i = 0; i < declaredFields.length; i++) {
if (i > 0) {
//如果类型是Integer
if (declaredFields[i].getGenericType().toString().equals("class java.lang.Integer")) {
Method m = (Method) entityclass.getClass().getMethod(
"get" + getMethodName(declaredFields[i].getName()));
Integer val = (Integer) m.invoke(entityclass);
param.setString(i, (val != null ? Integer.toString(val) : null));
}
//如果类型是String
if (declaredFields[i].getGenericType().toString().equals("class java.lang.String")) {
Method m = entityclass.getClass().getMethod("get" + getMethodName(declaredFields[i].getName()));
String parmeter = (String) m.invoke(entityclass);
param.setString(i, !StringUtils.isEmpty(parmeter) ? parmeter : null);
}
}
}
return param.executeUpdate() > 0 ? true : false;
} catch (SQLException e) {
e.printStackTrace();
} finally {
instance.free(rs, stat, conn);
}
return false;
}
/**
* 把头字母是小写替换成大写
*
* @throws Exception
*/
private static String getMethodName(String fieldName) throws Exception {
char[] charArray = fieldName.toCharArray();
int asiiValue = (int) charArray[0];
if (asiiValue >= 97 && asiiValue <= 122) {
byte[] items = fieldName.getBytes();
items[0] = (byte) ((char) items[0] - 'a' + 'A');
return new String(items);
} else {
return fieldName;
}
}
思考:如果表名跟类名不一样,获取不到类名,那是否可以在类上面写一个自定义注解,然后通过反射获取自定义注解的表名。
@MTable(name = "t_admin")
public class Admin {
}
注:获取自定义注解@MTable中的表名