http://blog.sina.com.cn/s/blog_4c925dca0100ehr0.html
动态sql这个话题,应该说不是什么新鲜事情了!但是,在一些特殊场合,我们就会要用到动态sql,如果是第一次去用动态sql的话,估计不会那轻松。这里阿堂把自己在项目中用动态sql的过程,和朋友们分享一下!
我这里所说的动态sql,是指的select语句中后面跟的字段是不确定的,是要根据实际业务来拼成的select语句。并不是简单指select后面的where条件是动态变化的
我的实际业务情况如下
运输公司在web页面,根据相应条件查询后,得到的select语句后字段都不确定,如,有时候,可能是select a,b,c,有时候可能又会是selecte,f,g,h,i,j等,然后,还要将这些查询得到的记录下载到excel文件中,也就是说每次查询后,得到的记录列字段都有可能不一样,生成的excel文件中的字段也是不一样的(除了行数,不确定外,列名也是不确定的),所以程序中就不能写死了,就得要去判断了,阿堂这里用到ResultSetMetaData类,实际上ResultSetMetaData应该是用到了反射技术的。。也就是我们只要得到一个ResultSet对象如rs,我们就可以得到
ResultSetMetaData类的对象了,进而,可以得到记录的总行数,记录的总列数,记录的列名,列字段的字段类型等,这时候,我们就可以将每一行记录封装到一个List对象中,然后,将每一个List对象,再封装到一个总的List对象中,最后利用jxl包中的一些方法,写入到excel文件中就可以了,当然,其中还会涉及到很多的细节性方面的东西,这不是我这里需要讨论的细节了,所以,我就不对此展开了,如有疑问,可以给阿堂单独留言咨询讨论!
(这是一个原来的项目,就是用的jdbc来操作的。。如果是这种动态的sql,用hibernate,ibatis这些框架处理起来就绝非易事了)
处理记录ResultSet集的类
public class MyTableModel extends AbstractTableModel {
private static final long serialVersionUID =-5361448825948488492L;
ResultSetrs;
ResultSetMetaData rsmd;
//以一个ResultSet结果集构造TableModel构造函数
publicMyTableModel(ResultSet rs)
{
this.rs=rs;
try{
rsmd=rs.getMetaData();
}
catch(Exception e)
{
e.printStackTrace();
}
}
//重写getColumnCount方法,用于设置该TableModel的列数
public intgetColumnCount()
{
try {
return rsmd.getColumnCount();
}
catch (SQLException e)
{
e.printStackTrace();
return 0;
}
}
//重写getRowCount方法,用于设置该TableModel的行数
public intgetRowCount() {
try{
rs.last();
return rs.getRow();
}
catch(Exception e)
{
e.printStackTrace();
return 0;
}
}
//重写getValueAt方法,用于设置该TableModel指定单元格的值
publicObject getValueAt(int row, int column) {
try{
rs.absolute(row+1); //定位到column列
returnrs.getObject(column+1);
}
catch(SQLException e)
{
e.printStackTrace();
return null;
}
}
//重写getColumnName方法,用于为该TableModel设置列名
publicString getColumnName(int c){
try{
return rsmd.getColumnName(c+1);
}
catch(SQLException e)
{
e.printStackTrace();
return null;
}
}
}
业务类中的一个处理方法
public ResultSet SelectBill3(Date sdate,Dateedate,String content,String username,String type) throwsSQLException
{
Date ed1=edate;
ed1.setDate(ed1.getDate()+1);
//如下这个要拼成动态sql语句a
StringBuffer str=newStringBuffer("");
StringBuffer sb=newStringBuffer("");
Stringstr1="";
String str11="";
if(type.equals("billdate"))
{
str11="selectdistinct fylx from BillOrderCheck bo,o_fy ofy wherebo.BillDate>=? andbo.BillDate<? andbo.UserName=? and bo.billno=ofy.zdbh";
str1="selectbo.BillNo as 帐单号,bo.BillDate as 帐单日期,bo.AllocateNo as派车单号,bo.OrderNo as 订单号,bo.TransDate as 运输日期,bo.VehicleNo as车牌,bo.CaseNo as 车型柜号,bo.Route as 行车路线,"
+"sum(o_fy.ysfje)as合计费用";
}
//运输日期 add by heyitang200903041335
if(type.equals("allocatenodate"))
{
str11="selectdistinct fylx from BillOrderCheck bo,o_fy ofy wherebo.TransDate>=? andbo.TransDate<? andbo.UserName=? and bo.billno=ofy.zdbh";
str1="selectbo.BillNo as 帐单号,bo.BillDate as 帐单日期,bo.AllocateNo as派车单号,bo.OrderNo as 订单号,bo.TransDate as 运输日期,bo.VehicleNo as车牌,bo.CaseNo as 车型柜号,bo.Route as 行车路线,"
+"sum(o_fy.ysfje)as合计费用";
}
//运输日期和派车单的组合条件 add by heyitang200903041335
if(type.equals("transAndDate"))
{
str11="selectdistinct fylx from BillOrderCheck bo,o_fy ofy wherebo.TransDate>=? and bo.TransDate<?and bo.AllocateNo=? and bo.UserName=? andbo.billno=ofy.zdbh";
str1="selectbo.BillNo as 帐单号,bo.BillDate as 帐单日期,bo.AllocateNo as派车单号,bo.OrderNo as 订单号,bo.TransDate as 运输日期,bo.VehicleNo as车牌,bo.CaseNo as 车型柜号,bo.Route as 行车路线,"
+"sum(o_fy.ysfje)as合计费用";
}
//帐单日期和派车单的组合条件
if(type.equals("allocatenoAndDate"))
{
str11="selectdistinct fylx from BillOrderCheck bo,o_fy ofy wherebo.BillDate>=? and bo.BillDate<? andbo.AllocateNo=? and bo.UserName=? andbo.billno=ofy.zdbh";
str1="selectbo.BillNo as 帐单号,bo.BillDate as 帐单日期,bo.AllocateNo as派车单号,bo.OrderNo as 订单号,bo.TransDate as 运输日期,bo.VehicleNo as车牌,bo.CaseNo as 车型柜号,bo.Route as 行车路线,"
+"sum(o_fy.ysfje)as合计费用";
}
Connection conn=null;
GetConnection gc=newGetConnection();
conn=gc.getConnection();
PreparedStatementpst=null;
ResultSet rs=null;
ResultSet rs1=null;
try
{
//拼接sql语句
pst=conn.prepareStatement(str11);
if(type.equals("billdate")|| type.equals("allocatenodate"))
{
pst.setDate(1,(java.sql.Date)sdate);
pst.setDate(2,(java.sql.Date) ed1);
pst.setString(3,username);
}
if(type.equals("allocatenoAndDate")|| type.equals("transAndDate"))
{
pst.setDate(1,(java.sql.Date)sdate);
pst.setDate(2,(java.sql.Date) ed1);
pst.setString(3,content.trim());
pst.setString(4,username);
}
rs1=pst.executeQuery();
intcount=0;
//获得并集最多的费用类型
while(rs1.next())
{
if(count>=1)str.append(";");
str.append(rs1.getString("fylx"));
//stradd.append(cs.converString(rs1.getString("fyzwmc")));
str.append("-");
str.append(getFyzwmc(rs1.getString("fylx")).replace("/",""));
count++;
}
rs1.close();
String[]strarr=str.toString().split(";");
sb.append(str1);
intlength=strarr.length;
Strings="",s1="",s3="",fylx1="",fyzwmc1="";
//下面循环得到拼接的动态sql语句
for(inti=0;i<length;i++)
{
sb.append(",");
//得到类似'YF'
s=strarr[i];
//System.out.println("strarr[i]"+strarr[i]);
fylx1=s.substring(0,s.indexOf("-"));
fyzwmc1=s.substring(s.indexOf("-")+1);
//得到类似ofy.YF
s1="o_fy.fylx";
s3="sum(case"+s1;
s3=s3+"when '"+fylx1+"' then ";
s3=s3+"o_fy.ysfje";
s3=s3+"else";
s3=s3+"0";
s3=s3+"end) as "+fyzwmc1;
sb.append(s3);
}
sb.append("from BillOrderCheck bo,allocate_m am,o_fy wherebo.allocateno=am.allocate_no and o_fy.zdbh=bo.billno");
//动态拼sql语句
if(type.equals("billdate"))
{
sb.append("and bo.BillDate>=? andbo.BillDate<? and bo.UserName=? ");
}
if(type.equals("allocatenodate"))
{
sb.append("and bo.TransDate>=? andbo.TransDate<? and bo.UserName=? ");
}
if(type.equals("allocatenoAndDate"))
{
sb.append("and bo.BillDate>=? and bo.BillDate<?and bo.AllocateNo=? and bo.UserName=? ");
}
if(type.equals("transAndDate"))
{
sb.append("and bo.TransDate>=? andbo.TransDate<? and bo.AllocateNo=? and bo.UserName=?");
}
sb.append("group byBillNo,BillDate,AllocateNo,OrderNo,TransDate,VehicleNo,CaseNo,bo.Route");
pst=conn.prepareStatement(sb.toString(),ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
if(type.equals("billdate")|| type.equals("allocatenodate"))
{
pst.setDate(1,(java.sql.Date)sdate);
pst.setDate(2,(java.sql.Date) ed1);
pst.setString(3,username);
}
if(type.equals("allocatenoAndDate")|| type.equals("transAndDate"))
{
pst.setDate(1,(java.sql.Date)sdate);
pst.setDate(2,(java.sql.Date) ed1);
pst.setString(3,content.trim());
pst.setString(4,username);
}
rs=pst.executeQuery();
booleanflag=false;
if(rs.next())
{
flag=true;
}
if(flag)
returnrs;
else
returnnull;
}
catch(SQLException e)
{
e.printStackTrace();
returnnull;
}
}
public List<Object>getList(MyTableModel model)
{
List<Object> list=newArrayList<Object>();
int a1=model.getColumnCount();
int a2=model.getRowCount();
List<Object> list1=newArrayList<Object>();
for(int j=0;j<a1;j++)
{
list1.add(model.getColumnName(j));
}
list.add(list1);
for(int i=0;i<a2;i++)
{
List<Object>list2=new ArrayList<Object>();
for(int j=0;j<a1;j++)
{
list2.add(model.getValueAt(i,j));
}
list.add(list2);
}
return list;
}