单表查询:通过反射机制实现根据不同实体类生成不同sql语句的工具类,ReflectUtil
使用本工具类要求表结构字段名和Java实体类对象名和实体类属性一一对应。
即数据库表名----->类名
数据库表字段名----->类属性(数据库名忽略大小写)
import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
*
*/
public class ReflectUtil {
/*
* 需求: 设计方法根据传入内容,动态生成insert语句
* 分析:
* 1.插入语句格式: insert into 表(字段名1,字段名2) values(值1,值2);
* 2.缺点:
* 缺点1:插入语句书写长度随着操作表中字段增加而无限增加
* insert into dept(deptno,dname,loc) values(?,?,?)
* insert into emp(empno,ename,job,mgr,sal,comm,hireDate,deptnO) values(?,?,?,?,?,?,?,?,?)
* 缺点2:将输入嵌入到占位符的开发工作量无法控制
*
* 3.插入语句组成结构
* insert into 表(字段名1,字段名2,字段名3) values(值1,值2);
* ----------- -- -------------------- ----------------
* 1 2 3 4
* 4.待解决问题:
* 问题1:如何动态判断出本次要操作【表名】
* 问题2:如何动态判断出当前表文件有【哪些字段】
* 问题3:使用何种容器盛放要添加的数据行内容
*
* 5.问题解决方案
* 问题3:使用何种容器盛放要添加的数据行内容-----使用表文件所对应实体类对象存放数据行内容
* 问题1:如何动态判断出本次要操作【表名】-------实体类的类名应该与对应的表名相同
* entity.getClass().getSimpleName();
* 问题2:如何动态判断出当前表文件有【哪些字段】----实体类的属性名应该与对应表文件的字段名相同
* entity.getClass().getDeclaredFields()
*/
public static String createInsert(Object entity)throws Exception{
String tableName=null;
StringBuffer sql = new StringBuffer("insert into ");
StringBuffer columns=new StringBuffer("(");
StringBuffer values=new StringBuffer(" values(");
Class classManager = entity.getClass();
Field fields[]=classManager.getDeclaredFields();
//1.得到【表名】
tableName = classManager.getSimpleName();
//2.得到【字段名】
//3.将数据行内容填充到values()---确保values中值内容与赋值字段【声明顺序保持一致】
for (Field field : fields) {
String colName= field.getName();
field.setAccessible(true);
Object value = field.get(entity);
if(value!=null){
//判断字段前方是否出现","
if(columns.length()>1){
columns.append(",");
values.append(",");
}
columns.append(colName);
values.append("'");
values.append(value);
values.append("'");
}
}
columns.append(")");
values.append(")");
//4.组装
sql.append(tableName);
sql.append(columns);
sql.append(values);
return sql.toString();
}
//update 表名 set 属性名=?,属性名=? where 主键(id)=?
public static String createUpdate(Object entity)throws Exception{
String tableName=null;
//用来存储完整的sql语句
StringBuffer sql = new StringBuffer("update ");
//用来存储set 后面的成分
StringBuffer set=new StringBuffer(" set ");
StringBuffer where=new StringBuffer(" where ");
//反射获取相关表名信息
Class classManager = entity.getClass();
//1.得到【表名】
tableName = classManager.getSimpleName();
//2.得到【字段名】
Field[] fieldList = classManager.getDeclaredFields();
//3.将数据行内容填充到set
for (int i = 1; i <fieldList.length ; i++) {
fieldList[i].setAccessible(true);
Object value = fieldList[i].get(entity);
if (value!=null){
//判断前方是否有字段出现
if (set.length()>5){
set.append(",");
}
String name = fieldList[i].getName();
set.append(name);
set.append("=");
set.append("'");
set.append(value);
set.append("'");
}
}
//where后面部分处理
fieldList[0].setAccessible(true);
String name = fieldList[0].getName();
Object value = fieldList[0].get(entity);
where.append(name);
where.append("=");
where.append(value);
//4.组装
sql.append(tableName);
sql.append(set);
sql.append(where);
return sql.toString();
}
/*
* 需求:设计一个方法,自动的将结果集中数据行内容存放到指定的实体类对象
* 传统结果集映射
* while(rs.next()){
int deptNo = rs.getInt("deptNo");
String dname =rs.getString("dname");
String loc=rs.getString("loc");
Dept dept = new Dept(deptNo, dname, loc);
list.add(dept);
}
*/
public static List selectList(ResultSet rs, Class entityClass)throws Exception{
List list = new ArrayList();
//得到实体类所有属性的管理对象
Field fields[]=entityClass.getDeclaredFields();
while(rs.next()){
//创建一个实体类对象
Object obj=entityClass.newInstance();
//读取游标指向的数据行中字段内容
for (Field field : fields) {
String colName =field.getName();
String value= null;
try {
value = rs.getString(colName);
} catch (SQLException e) {
continue;
}
String typeName = field.getType().getSimpleName();
if(value!=null){
//将数据行字段内容存放到实体类对象中同名属性
field.setAccessible(true);
if("Integer".equals(typeName)){
field.set(obj,Integer.valueOf(value));
}else if("Double".equals(typeName)){
field.set(obj,Double.valueOf(value));
}else if("String".equals(typeName)){
field.set(obj,value);
}
}
}
//将实体类对象存放到List
list.add(obj);
}
return list;
}
}