所谓动态查询,就是查询的时候,不确定查询的列数,也不确定查询的哪几个列.
通过反射可以完成这个操作:
我们在构造sql语句的时候,动态传入条件.在结果集中,通过获取结果集的列名,来进行赋值.
* 针对于表的字段名与类的属性名不相同的情况:
* 1. 必须声明sql时,使用类的属性名来命名字段的别名
* 2. 使用ResultSetMetaData时,需要使用getColumnLabel()来替换getColumnName(),
* 获取列的别名。
* 说明:如果sql中没有给字段其别名,getColumnLabel()获取的就是列名
我们这样构造查询函数:
public Customer queryForCustomers(String sql,Object...args){}
然后这样还原sql语句
ps =conn.prepareStatement(sql);for(int i = 0;i < args.length;i++){
ps.setObject(i+ 1, args[i]);
}
然后这样利用反射构造javabean
//获取结果集的元数据 :ResultSetMetaData
ResultSetMetaData rsmd =rs.getMetaData();//通过ResultSetMetaData获取结果集中的列数
int columnCount =rsmd.getColumnCount();if(rs.next()) {
Customer cust= newCustomer();//处理结果集一行数据中的每一个列
for (int i = 0; i < columnCount; i++) {//获取列值
Object columValue = rs.getObject(i + 1);//获取每个列的列名
String columnLabel = rsmd.getColumnLabel(i + 1);//给cust对象指定的columnName属性,赋值为columValue:通过反射
Field field = Customer.class.getDeclaredField(columnLabel);
field.setAccessible(true);
field.set(cust, columValue);
}
}
完整代码
publicCustomer queryForCustomers(String sql,Object...args){
Connection conn= null;
PreparedStatement ps= null;
ResultSet rs= null;try{
conn=JDBCUtils.getConnection();
ps=conn.prepareStatement(sql);for(int i = 0;i < args.length;i++){
ps.setObject(i+ 1, args[i]);
}
rs=ps.executeQuery();//获取结果集的元数据 :ResultSetMetaData
ResultSetMetaData rsmd =rs.getMetaData();//通过ResultSetMetaData获取结果集中的列数
int columnCount =rsmd.getColumnCount();if(rs.next()){
Customer cust= newCustomer();//处理结果集一行数据中的每一个列
for(int i = 0;i
Object columValue = rs.getObject(i + 1);//获取每个列的列名//String columnName = rsmd.getColumnName(i + 1);
String columnLabel = rsmd.getColumnLabel(i + 1);//给cust对象指定的columnName属性,赋值为columValue:通过反射
Field field = Customer.class.getDeclaredField(columnLabel);
field.setAccessible(true);
field.set(cust, columValue);
}returncust;
}
}catch(Exception e) {
e.printStackTrace();
}finally{
JDBCUtils.closeResource(conn, ps, rs);
}return null;
}
View Code
这个代码是针对一张表的查询,我们可以利用泛型,编写查询任意表的通用操作
public T getInstance(Class cl,String sql,Object ...args)throwsException{
InputStream is= connectTest.class.getClassLoader().getResourceAsStream("jdbcInfo.properties");
Properties pro= newProperties();
pro.load(is);
String user= pro.getProperty("user");
String password= pro.getProperty("password");
String url= pro.getProperty("url");
String driverClass= pro.getProperty("driverClass");//利用反射
Connection connection = null;
PreparedStatement ps= null;
ResultSet rs= null;
T t= null;try{
Class.forName(driverClass);
connection=DriverManager.getConnection(url,user,password);
System.out.println(connection);
ps=connection.prepareStatement(sql);for(int i=0;i
ps.setObject(i+1,args[i]);
rs=ps.executeQuery();//获取结果集的元数据
ResultSetMetaData md =rs.getMetaData();//获取结果集元数据中的列数
int columnCount =md.getColumnCount();if(rs.next()){//利用反射动态加载数据
t =cl.newInstance();for(int i=0;i
Object colDate= rs.getObject(i+1);
String colName= md.getColumnLabel(i+1);
Field var=cl.getDeclaredField(colName);
var.setAccessible(true);
var.set(t,colDate);
}
System.out.println(t);returnt;
}
}catch(ClassNotFoundException e) {
e.printStackTrace();
}catch(SQLException e) {
e.printStackTrace();
}finally{if(ps!=null)try{
ps.close();
}catch(SQLException e) {
e.printStackTrace();
}if(connection!=null)try{
connection.close();
}catch(SQLException e) {
e.printStackTrace();
}if(rs!=null){try{
rs.close();
}catch(SQLException e) {
e.printStackTrace();
}
}returnt;
}
利用泛型查询任意表