问题:IO输出多个字段,取的三张表的字段也不一样,1.如何在输出的文件表中添加String类型的相应组长的字段???要求要和表1、表2、表3的字段相对应!!!
2.如何先先输出第一行标题,然后再循环输出表的内容??3.如何添加一列字段计算合计:(业务量*单价)??4.怎样将null值显示为没有值??输出为:
组长 业务量 单价 员工编号 经理 地区 合计
组长1 A B C null null A*B
.... .. ... ... ... ... ...
组长2 D E F null G D*E
.... ... .. .. ... ... ...
组长3 H I J K null H*I
.... .. .. ... ... ... ...
import java.sql.*;
import java.util.*;
import java.io.*;public class test extends ClassObj{
public static void main(String[] args) throws Exception {
try {
ArrayList<ClassObj> lst = test.getResultLst();
String contents = test.formatLst(lst);
String fileName = "C:\\result.txt";
test.saveFile(fileName, contents);
} catch (Exception e) {
e.printStackTrace();
}
}
static ArrayList<ClassObj> getResultLst() throws Exception {
String url = "jdbc:odbc:study";
String user = "sa";
String password = "123";
ArrayList <ClassObj> lst = new ArrayList <ClassObj>();
Connection con = null;
Connection con2 = null;
Connection con3 = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
ResultSet rs2 = null;
ResultSet rs3 = null;
String sql = "select 业务量 as A,单价 as B,员工编号 as C from 表1";
String sql2 = "select 业务量 as D,单价 as E,员工编号 as F,地区 as G from 表2";
String sql3 = "select 业务量 as H,单价 as I,员工编号 as J,经理 as K from 表3";
try{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
con = DriverManager.getConnection(url,user,password); pstmt = con.prepareStatement(sql);
pstmt2 = con.prepareStatement(sql2);
pstmt3 = con.prepareStatement(sql3);
rs = pstmt.executeQuery();
rs2 = pstmt2.executeQuery();
rs3 = pstmt3.executeQuery();
String fa = "组长1";
String fb = "组长2";
String fc = "组长3";
ClassObj c1=null;
while(rs.next()){ //怎样将fa,fb,fc跟相应的rs,rs2,rs3对应循环输出。
c1=new ClassObj(); //c1.setBand(rs.getString("fa"));?????
c1.setBuss(rs.getDouble("A"));
c1.setPrice(rs.getDouble("B"));
c1.setId(rs.getString("C"));
//怎么才能计算合并输出????
//c1.setId(rs.getDouble(A*B));
lst.add(c1);
}
while(rs2.next()){
c1=new ClassObj();
c1.setBuss(rs.getDouble("D"));
c1.setPrice(rs.getDouble("E"));
c1.setId(rs.getString("F"));
c1.setLand(rs.getString("G"));
lst.add(c1);
}
while(rs3.next()){
c1=new ClassObj();
c1.setBuss(rs.getDouble("H"));
c1.setPrice(rs.getDouble("I"));
c1.setId(rs.getString("J"));
c1.setMan(rs.getString("K"));
lst.add(c1);
} }catch(Exception e){
e.printStackTrace();
}finally{
try{
if (rs != null)
rs.close();
if (pstmt != null)
pstmt.close();
if (con != null)
con.close();
}catch(Exception e){}
}
}
static void saveFile(String fileName, String contents)
throws IOException {
File f = new File(fileName); if (f.exists()){
throw new IOException("file exists...");
}
if (!f.createNewFile()) {
throw new IOException("file create failure...");
} try {
BufferedWriter output = new BufferedWriter(new FileWriter(f));
output.write(contents);
output.close();
} catch (Exception e) {
throw new IOException(e);
}
} static String formatLst(ArrayList <ClassObj> lst){
String contents = ""; //如何在这先循环第一行标题??
for(int i=0;i <lst.size();i++){
contents +=lst.get(i).getBand+"\t"+lst.get(i).getBuss+"\t"+lst.get(i).getPrice+"\t"+lst.get(i).getId+"\t"+lst.get(i).getLand+lst.get(i).getMan+"\t"+lst.get(i).getSum+"\n";
}
return contents;
}
}
class ClassObj {
private String Band; private Double Buss; private Double Price;
private String Id;
private String Land;
private String Man;
private Double Sum;
//get..set
public String toString() {
return "ClassObj{classBand=" + this.classBand +",classId="
+ this.classId + ",classGroup="
+ this.classGroup + ",classSum="
+ this.classSum + ",classNo=" + this.classNo +"}";
}
}
2.如何先先输出第一行标题,然后再循环输出表的内容??3.如何添加一列字段计算合计:(业务量*单价)??4.怎样将null值显示为没有值??输出为:
组长 业务量 单价 员工编号 经理 地区 合计
组长1 A B C null null A*B
.... .. ... ... ... ... ...
组长2 D E F null G D*E
.... ... .. .. ... ... ...
组长3 H I J K null H*I
.... .. .. ... ... ... ...
import java.sql.*;
import java.util.*;
import java.io.*;public class test extends ClassObj{
public static void main(String[] args) throws Exception {
try {
ArrayList<ClassObj> lst = test.getResultLst();
String contents = test.formatLst(lst);
String fileName = "C:\\result.txt";
test.saveFile(fileName, contents);
} catch (Exception e) {
e.printStackTrace();
}
}
static ArrayList<ClassObj> getResultLst() throws Exception {
String url = "jdbc:odbc:study";
String user = "sa";
String password = "123";
ArrayList <ClassObj> lst = new ArrayList <ClassObj>();
Connection con = null;
Connection con2 = null;
Connection con3 = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
ResultSet rs2 = null;
ResultSet rs3 = null;
String sql = "select 业务量 as A,单价 as B,员工编号 as C from 表1";
String sql2 = "select 业务量 as D,单价 as E,员工编号 as F,地区 as G from 表2";
String sql3 = "select 业务量 as H,单价 as I,员工编号 as J,经理 as K from 表3";
try{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
con = DriverManager.getConnection(url,user,password); pstmt = con.prepareStatement(sql);
pstmt2 = con.prepareStatement(sql2);
pstmt3 = con.prepareStatement(sql3);
rs = pstmt.executeQuery();
rs2 = pstmt2.executeQuery();
rs3 = pstmt3.executeQuery();
String fa = "组长1";
String fb = "组长2";
String fc = "组长3";
ClassObj c1=null;
while(rs.next()){ //怎样将fa,fb,fc跟相应的rs,rs2,rs3对应循环输出。
c1=new ClassObj(); //c1.setBand(rs.getString("fa"));?????
c1.setBuss(rs.getDouble("A"));
c1.setPrice(rs.getDouble("B"));
c1.setId(rs.getString("C"));
//怎么才能计算合并输出????
//c1.setId(rs.getDouble(A*B));
lst.add(c1);
}
while(rs2.next()){
c1=new ClassObj();
c1.setBuss(rs.getDouble("D"));
c1.setPrice(rs.getDouble("E"));
c1.setId(rs.getString("F"));
c1.setLand(rs.getString("G"));
lst.add(c1);
}
while(rs3.next()){
c1=new ClassObj();
c1.setBuss(rs.getDouble("H"));
c1.setPrice(rs.getDouble("I"));
c1.setId(rs.getString("J"));
c1.setMan(rs.getString("K"));
lst.add(c1);
} }catch(Exception e){
e.printStackTrace();
}finally{
try{
if (rs != null)
rs.close();
if (pstmt != null)
pstmt.close();
if (con != null)
con.close();
}catch(Exception e){}
}
}
static void saveFile(String fileName, String contents)
throws IOException {
File f = new File(fileName); if (f.exists()){
throw new IOException("file exists...");
}
if (!f.createNewFile()) {
throw new IOException("file create failure...");
} try {
BufferedWriter output = new BufferedWriter(new FileWriter(f));
output.write(contents);
output.close();
} catch (Exception e) {
throw new IOException(e);
}
} static String formatLst(ArrayList <ClassObj> lst){
String contents = ""; //如何在这先循环第一行标题??
for(int i=0;i <lst.size();i++){
contents +=lst.get(i).getBand+"\t"+lst.get(i).getBuss+"\t"+lst.get(i).getPrice+"\t"+lst.get(i).getId+"\t"+lst.get(i).getLand+lst.get(i).getMan+"\t"+lst.get(i).getSum+"\n";
}
return contents;
}
}
class ClassObj {
private String Band; private Double Buss; private Double Price;
private String Id;
private String Land;
private String Man;
private Double Sum;
//get..set
public String toString() {
return "ClassObj{classBand=" + this.classBand +",classId="
+ this.classId + ",classGroup="
+ this.classGroup + ",classSum="
+ this.classSum + ",classNo=" + this.classNo +"}";
}
}
合计是前2个字段的乘积,可以在遍历结果集时放到对象的sum字段中,也可以在显示时用2个字段的乘积表示static String formatLst(ArrayList <ClassObj> lst){
//2.如何先先输出第一行标题,然后再循环输出表的内容??
//2.标题是固定的,不能写死吗?
String contents = "组长 业务量 单价 员工编号 经理 地区 合计 "; //如何在这先循环第一行标题??
String band = "";
String ……
for(int i=0;i <lst.size();i++){
4.怎样将null值显示为没有值??输出为:
band = lst.get(i).getBand() == null ? "" : lst.get(i).getBand();
……
contents += band +"\t"+lst.get(i).getBuss+"\t"+lst.get(i).getPrice+"\t"+lst.get(i).getId+"\t"+lst.get(i).getLand+lst.get(i).getMan+"\t"+lst.get(i).getSum+"\n";
}
return contents;
}
}
这里指出几个疑点,不对的话请高手指正了。
1.代码中
pstmt = con.prepareStatement(sql);
pstmt2 = con.prepareStatement(sql2);
pstmt3 = con.prepareStatement(sql3);
rs = pstmt.executeQuery();
rs2 = pstmt2.executeQuery();
rs3 = pstmt3.executeQuery();
但是
finally{
try{
if (rs != null)
rs.close();
if (pstmt != null)
pstmt.close();
if (con != null)
con.close();
}catch(Exception e){}
}虽然最后con关了,但我觉得好习惯还是rs和stmt2.你开3个sql来查,其实一个sql就可以搞定你要的那个表格形式了。3.btw:6楼,他的sql的表头可能会随时加上另外的一列,所以代码里面估计他不能写死。
可以先
String title = "";
if(lst!=null&&lst.size()>0){
title = lst.get(0).get***+*****+\n;
}
下面的for从i=1开始计算,当然要判断lst.size()>1。
我先试试大家给出的主意!
c1=new ClassObj(); //c1.setBand(rs.getString("fa"));?????这儿应该有个for循环!
c1.setBuss(rs.getDouble("A"));
c1.setPrice(rs.getDouble("B"));
c1.setId(rs.getString("C"));
//请问如何在遍历结果集时放到对象的sum字段中????能讲的详细点吗??
//c1.setId(rs.getDouble(A*B));????
lst.add(c1);
}
六楼的朋友写的输出标题的方法和解决null方法看明白了,七楼的朋友“不能写死”的代码没有看明白,能给写的再具体点吗??
1.如果你每一行都要加上组长:张三的话,那你就在ClassObj里面再加个属性标识组长,然后在rs的每个while里面分别set进去。输出的时候再get出来。比如 while(rs.next()){ //怎样将fa,fb,fc跟相应的rs,rs2,rs3对应循环输出。
c1=new ClassObj(); //c1.setBand(rs.getString("fa"));?????
c1.setCaptain("组长:张三"); //第一个结果集的组长
c1.setBuss(rs.getDouble("A"));
c1.setPrice(rs.getDouble("B"));
c1.setId(rs.getString("C"));
//怎么才能计算合并输出????
//c1.setId(rs.getDouble(A*B));
lst.add(c1);
}
while(rs2.next()){
c1=new ClassObj();
c1.setCaptain("组长:李四"); //第二个结果集的组长
c1.setBuss(rs.getDouble("D"));
c1.setPrice(rs.getDouble("E"));
c1.setId(rs.getString("F"));
c1.setLand(rs.getString("G"));
lst.add(c1);
}
while(rs3.next()){
c1=new ClassObj();
c1.setCaptain("组长:王五"); //第三个结果集的组长
c1.setBuss(rs.getDouble("H"));
c1.setPrice(rs.getDouble("I"));
c1.setId(rs.getString("J"));
c1.setMan(rs.getString("K"));
lst.add(c1);
}
2.合计的问题不知道你解决了没有,可以修改sql
String sql = "select 业务量 as A,单价 as B,员工编号 as C,NVL(业务量,0)*NVL(单价,0) as HJ from 表1";
String sql2 = "select 业务量 as D,单价 as E,员工编号 as F,地区 as G,NVL(业务量,0)*NVL(单价,0) as HJ from 表2";
String sql3 = "select 业务量 as H,单价 as I,员工编号 as J,经理 as K,NVL(业务量,0)*NVL(单价,0) as HJ from 表3";
然后,在你的while中,同样可以get到 HJ这列,然后set到ClassObj中去。
或者,你的 //怎么才能计算合并输出????
//c1.setId(rs.getDouble(A*B));
用 c1.set合计 (rs.getDouble("A")*rs.getDouble("B")); //double的乘法是不是这样我忘了,不好意思。
3.你的表头,如果是在每个结果集的最先都要加,那你参照办法1,在每个while(rs.next())的前面,new一个ClassObj,把表头set进去,再把这个ClassObj添加到你的列表里面。ArrayList是顺序的,所以不会乱。
如果只要第一行加,那就只在第一个while(rs.next())的前面,new一个ClassObj,把表头set进去。
c0.setCaptain("组长");
c0.setBuss("业务量");
c0.setPrice("单价");
c0.setId("员工编号");
c0.setLand("地区");
c0.setMan("经理");
lst.add(c0);
while(rs.next()){
......
}
表头是这么写吗??
还想问个问题如果第一天跑了50条记录,第二天我想紧跟着从第51条开始跑第二天的记录怎样才能实现这个需求???
对就这么加。不知道你的表里面有没有日期,如果有日期就好办。你在where条件里面加上
where to_char(日期字段,'YYYYMMDD') = to_char(sysdate,'YYYYMMDD')
就可以只查当天的记录。
sysdate 是系统日期。
系统日期可以通过数字来调整。比如,你要查当天的前一天,你就把上面的where的sysdate改成sysdate-1.
你还可以通过系统日期来精确到秒。比如,你要查当天的8点30分30秒之前的,就可以用
where to_char(日期字段,'YYYYMMDDHH24MISS') < to_char(sysdate,'YYYYMMDD')||'083030'
表头
第1条。。
第2条。。
第3条。。
第4条。。
第5条。。
新的数据--》 第6条。。
。。
还有一个问题,要是想运行一次查2个SQL并且分别输出到两个txt文件,需要在代码里改哪些地方??
c1.set合计 (getSum(rs.getDouble(A),rs.getDouble(B)));
.....
static double getSum(Double A,Double B){
return A*B;
}
合计的问题还是没解决,还要麻烦大家跟想想办法。
文件追加,只要把saveFile改一下,见注释: static void saveFile(String fileName, String contents) throws IOException {
File f = new File(fileName);
BufferedWriter output = null;
try {
//如果不存在
if (!f.exists()) {
//建新文件
if (!f.createNewFile()) {
throw new IOException("file create failure...");
}
}
//这里的 true表示文件追加,false表示原来的都不要
output = new BufferedWriter(new FileWriter(f, true));
output.write(contents); } catch (Exception e) {
e.printStackTrace();
} finally {
//最后在finally关闭
try {
output.close(); } catch (Exception e) { }
}
} 还有一个问题,要是想运行一次查2个SQL并且分别输出到两个txt文件,需要在代码里改哪些地方??
那就调两次saveFile,你要存到两个文件里面的分别用不同的ArrayList。或者你存完第一个之后,将ArrayList清空,再查第二个sql的结果放到第一个里面去。
你用SQL Server噢,NVL是oracle的,我上次以为你用oracle~~~.NVL(param1,param2)的意思是:如果param1为NULL,则输出param2.你看看SQLSERVER里面有没有类似的函数。
(rs.getDouble("A")*rs.getDouble("B"));运行时报错。我上次写的时候忘了rs.getDouble("B")是得到一个Double对象,而不是一个double值,用
rs.getDouble("A").doubleValue()*rs.getDouble("B").doubleValue() 就可以了,不过要求你数据库输出的必须是double或整数。
或者也可以
static double getSum(Double A, Double B) {
return A.doubleValue() * B.doubleValue();
}
兩個解決方案:
一、編寫SQL搞定,比如用聚合函數等。
二、定義javabean ,把你所要用到的元素都包含進去。如果有要計算的字段,比如(業務金額 字段中,就可以在其 get()方法中寫入:業務量*單價。等等。
再用List<javabean> 去裝數據。 你就資料庫中抓出來往裡面扔吧,有多少扔多少,想怎麼扔就怎麼扔。
1.调两次saveFile,你要存到两个文件里面的分别用不同的ArrayList,这个方法搞明白了!十分感谢。
2.存完第一个之后,将ArrayList清空,再查第二个sql的结果放到第一个里面去。这种方法不太明白,能具体写下代码吗??
关于合计如果当数据库表中的相应字段类型不是Double,而是String或Float或int类型时,分别应当如何转换类型???
1.运行cmd。2.进入C盘根目录。3.执行javac test.java命令。4.执行java test命令。
并能够保持在cmd窗口显示执行java test之后的内容。
2.存完第一个之后,将ArrayList清空,再查第二个sql的结果放到第一个里面去。这种方法不太明白,能具体写下代码吗??
简单写下:
ArrayList<..> lst = new ArrayList<..>();
...
rs = execute sql
while(rs.next){
...
lst.add(...)
}
...
saveFile(..);lst = new ArrayList<..>();
再来一次~~~ 关于合计如果当数据库表中的相应字段类型不是Double,而是String或Float或int类型时,分别应当如何转换类型???
这个String要看你数据库里面有没有小数点,有的话用rs.getString(...)后用Double转换,然后就可以跟Double一样。没小数点,就用Integer.parserInt(String s)转成Integer,然后再Integer.intValue去乘。int的直接rs.getInt直接乘。Float的不晓得,没用过这么高级的。
这些其实你都可以google或百度得到的。
你是想写完程序点下这个文件就看结果?搞这么麻烦还不如直接在IDE里面 run as java bean或run as java application 来得快。
如果你做完了要写.bat文件,那倒是另一回事。
cd D://你class放得路径TOOLBAR
java -classpath "./lib/jdom.jar;./lib/log4j-1.2.15.jar" com.socix.financial.AppLauncher-classpath的值"./lib/jdom.jar;./lib/log4j-1.2.15.jar"指名你用到的所有jar的路径,com.socix.financial.AppLauncher就是你那个有main方法的类名。
2、日期还是上面的格式,我想同时取2009-11-02,2009-11-10至2009-11-15,2009-11-17至2009-11-19这三个时间段的数据where应该怎么写时间范围?
2:between...and...
while (rs.next()) {
c1 = new ClassObj();
c1.setClassId(rs.getString("A"));
c1.setClassGroup(rs.getString("B"));
c1.setClassNo(rs.getString("C"));
lst.add(c1);
}
.....
static String format(ArrayList<ClassObj> lst) {
String contents = "";
String Gg = "组长"; for (int i = 0; i < lst1.size(); i++) {
String sa=lst.get(i).getClassId(); //要在这一层将String类型A、B转换成int类型相乘并循环输出,这一段代码应该怎么写??
String sb=lst.get(i).getClassGroup();//??
int Gd =(Integer.parserInt(String (sa))).intValue*(Integer.parserInt(String (sb))).intValue;//?????
contents += Gg+"\t"+lst.get(i).getClassId() +"\t"+lst.get(i).getClassGroup()+"\t"+ Gd +"\n";
}
return contents;
}
数据类型这块知识还有些模糊,麻烦帮忙给写写代码。
convert(varchar(10),date_col,121)) between '2009-11-17' and '2009-11-19' )
String total = "";
String sa=lst.get(i).getClassId(); //要在这一层将String类型A、B转换成int类型相乘并循环输出,这一段代码应该怎么写??
String sb=lst.get(i).getClassGroup();//??
try{
//可以转换为int的乘起来再变成string
total = String.valueOf(Integer.parseInt(sa)*Integer.parseInt(sb));
}catch(Exception e){
//不可以转换的例如字母字符、null等等,让总计变零
total = "0";
}
System.out.println(total);
//int Gd =(Integer.parserInt(String (sa))).intValue*(Integer.parserInt(String (sb))).intValue;//?????
contents += Gg+"\t"+lst.get(i).getClassId() +"\t"+lst.get(i).getClassGroup()+"\t"+ total +"\n";
}
。
while(rs2.next()){
c1=new ClassObj();
c1.setBuss(rs.getString("A")); //运行时报错,convert()是什么类型的,为什么用String取不出来?
c1.setPrice(rs.getString("B"));
c1.setId(rs.getString("C"));
lst.add(c1);
}
convert(char(10),wdate,120) 改为121
这个意思好像就是把你的wdate转为"yyyy-mm-dd"的字符串。
说实话,mysql我没用过。你baidu或者google一把 mysql 日期转换函数,应该一堆出来的。我也是查的。
两个选择:
1.调用saveFile之后,再for循环lst一把,然后把lst里面的数据一条条的insert回去。
2.如果不是实时的,就是说,你今天生成文件,明天写回去,那么你就读文件,读一行insert一行或者整个文件都读完再一起for循环写回去。。
* 逐行文件写回数据库,可以把里面的if (c.length == 7) {}包含的这段独立拿出来作为一个方法,我懒得改了。
*
* @param fileName
* 文件名
* @param con
* jdbc连接对象,在外部连上后传入。外部调用的函数要记得关闭。
* @throws Exception
*/
public static void readFileWriteBack(String fileName, Connection con)
throws Exception {
String s = "";
File f = new File(fileName);
if (!f.exists()) {
throw new Exception("file doesn't exist....");
}
BufferedReader br = null;
PreparedStatement pstmt = null;
try {
br = new BufferedReader(new InputStreamReader(
new FileInputStream(f))); while ((s = br.readLine()) != null) {
// 如果这行有合计,表示是属于表头,忽略掉这行
if (s.indexOf("合计") > 0) {
continue;
}
// 将这行拆分开,按你已有格式:组长 业务量 单价 员工编号 经理 地区 合计
String[] c = s.split("\t");
printArray(c);// 打印看看数据对不对,这行可去掉
// 只有这行拆出来是7个数据才写入数据库,对应你的文件,你写了几个,这里改成几
if (c.length == 7) {
// tbl_report是要写回的数据表,最好
String sql = "insert into tbl_report(组长,业务量,单价,员工编号,经理,地区,合计)"
+ "values(?,?,?,?,?,?,?)";
pstmt = con.prepareStatement(sql);
// 第一个参数代表sql中的第几个问号,第二个参数代表从文件中取出的每行数据的
// 转换成数组后的值。
pstmt.setString(1, c[0]);
pstmt.setString(2, c[1]);
// 单价这行不知道你数据类型,如果int就用setInt,如果小数,可用setBigDecimal(new
// BigDecimal(c[2]));其他数字类型同理。
pstmt.setString(3, c[2]);
pstmt.setString(4, c[3]);
pstmt.setString(5, c[4]);
pstmt.setString(6, c[5]);
pstmt.setString(7, c[6]);
pstmt.execute();
}
} System.out.println("file write back finished");
} catch (Exception e) {
throw e;
} finally {
try {
if (pstmt != null) {
pstmt.close();
}
br.close();
} catch (Exception e) {
e.printStackTrace();
}
}
} /**
* savaFile后,ArrayList数据写回数据库,可以把里面的if (!man.equals("经理")) {}包含的这段调用
* 我在readFileWriteBack这里说的,如果你独立把它拿出来了的话。
*
* @param lst
* savaFile完了之后的ArrayList
* @param con
* jdbc连接对象,在外部连上后传入。外部调用的函数要记得关闭。
* @throws Exception
*/
public static void readListWriteBack(ArrayList<ClassObj> lst, Connection con)
throws Exception {
PreparedStatement pstmt = null;
try { for (int i = 0; i < lst.size(); i++) {
ClassObj co = lst.get(i);
// 如果这行有经理,表示是属于表头,忽略掉这行,(可以跟上面一样采用合计,
// 我这里不知道你合计的属性是什么
String man = co.getMan();
if (!man.equals("经理")) {
// tbl_report是要写回的数据表,最好
String sql = "insert into tbl_report(组长,业务量,单价,员工编号,经理,地区,合计)"
+ "values(?,?,?,?,?,?,?)";
pstmt = con.prepareStatement(sql);
// 第一个参数代表sql中的第几个问号,第二个参数代表从ClassObj中取出的每个数据
// co的属性,与insert的问号一一对应。请自己修改。
pstmt.setString(1, co.getClassGroup());
pstmt.setString(2, co.getClassGroup());
// 单价这行不知道你数据类型,如果int就用setInt,如果小数,可用setBigDecimal(new
// BigDecimal(co.getClassGroup()));其他数字类型同理。
pstmt.setString(3, co.getClassGroup());
pstmt.setString(4, co.getClassGroup());
pstmt.setString(5, co.getClassGroup());
pstmt.setString(6, co.getClassGroup());
pstmt.setString(7, co.getClassGroup());
pstmt.execute();
}
} System.out.println("arraylist write back finished");
} catch (Exception e) {
throw e;
} finally {
try {
if (pstmt != null) {
pstmt.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
} public static void printArray(String[] a) {
for (int i = 0; i < a.length; i++) {
System.out.print(a[i] + " ");
}
System.out.println();
}
个人感觉是con的关闭有问题
java.sql.SQLException: [Microsoft][ODBC SQL Server Driver]连接占线导致另一个 hstmt
import java.sql.*;
import java.util.*;
import java.io.*;public class testReaderFile{
public static void main(String[] args) throws Exception {
try{
String url = "jdbc:odbc:study";
String user = "sa";
String password = "123";
Connection con = null;
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
con = DriverManager.getConnection(url, user, password);
String fileName = "C:\\result.txt";
testReaderFile.readFileWriteBack(fileName, con);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void readFileWriteBack(String fileName, Connection con) throws Exception {
String s = "";
File f = new File(fileName);
if (!f.exists()) {
throw new Exception("file doesn't exist....");
}
BufferedReader br = null;
PreparedStatement pstmt = null;
try {
br = new BufferedReader(new InputStreamReader(new FileInputStream(f))); while ((s = br.readLine()) != null) {
if (s.indexOf("统计量") > 0) {
continue;
}
String[] c = s.split("\t");
//System.out.println(c);
if (c.length == 4) {
String sql = "insert into tbl_report(单价,工号,统计量,日期)"
+ "values(?,?,?,?)";
pstmt = con.prepareStatement(sql);
pstmt.setString(1, c[0]);
pstmt.setString(2, c[1]);
pstmt.setString(3, c[2]);
pstmt.setString(4, c[3]);
pstmt.execute();
}
} System.out.println("file write back finished");
} catch (Exception e) {
throw e; //可能是这里的异常没处理好,con的关闭有问题。
} finally {
try {
if (pstmt != null) {
pstmt.close();
}
if (con != null) {
con.close();
}
br.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
pstmt.execute();
后面加上
pstmt.close();
我测试过了,用的oracle数据库。
public static void readFileWriteBack(String fileName, Connection con)
throws Exception {
String s = "";
File f = new File(fileName);
if (!f.exists()) {
throw new Exception("file doesn't exist....");
}
BufferedReader br = null;
PreparedStatement pstmt = null;
try {
br = new BufferedReader(new InputStreamReader(
new FileInputStream(f)));
String sql = "insert into tbl_report(单价,工号,统计量,日期)"
+ "values(?,?,?,'2009-12-07')";
pstmt = con.prepareStatement(sql);
//循环外部准备好prepareStatement;
while ((s = br.readLine()) != null) {
if (s.indexOf("合计") > 0) {
continue;
}
String[] c = s.split("\t");
printArray(c);
if (c.length == 3) {
//加入批量参数
pstmt.setString(1, c[0]);
pstmt.setString(2, c[1]);
pstmt.setString(3, c[2]);
pstmt.addBatch();
}
}
//一次执行。
pstmt.executeBatch();
System.out.println("file write back finished");
} catch (Exception e) {
throw e;
} finally {
try {
if (pstmt != null) {
pstmt.close();
}
br.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
throws Exception {
PreparedStatement pstmt = null;
try {
// tbl_report是要写回的数据表,最好
String sql = "insert into tbl_report(单价,工号,统计量,日期)"
+ "values(?,?,?,'2009-12-07')";
pstmt = con.prepareStatement(sql);
for (int i = 0; i < lst.size(); i++) {
ClassObj co = lst.get(i);
String man = co.getMan();
if (!man.equals("经理")) {
pstmt.setString(1, co.getClassGroup());
pstmt.setString(2, co.getClassGroup());
pstmt.setString(3, co.getClassGroup());
pstmt.addBatch();
}
}
pstmt.executeBatch();
System.out.println("arraylist write back finished");
} catch (Exception e) {
throw e;
} finally {
try {
if (pstmt != null) {
pstmt.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws Exception {
Connection con = null;
try {
ArrayList<ClassObj> lst = new ArrayList<ClassObj>();// test6.getResultLst();
int i = 0;
while (i++ < 2000) {
ClassObj obj = new ClassObj();
obj.setClassId("A" + i);
obj.setClassGroup("B" + i);
obj.setClassNo("C" + i);
obj.setMan("D" + i);
lst.add(obj);
}
String fileName = "E:\\result.dat";
// String contents = ReadWriteListFile.formatLst(lst);
// saveFile(fileName, contents);
con = OConnection.getConn();
ReadWriteListFile.readListWriteBack(lst, con);
// readFileWriteBack(fileName, con);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (con != null) {
con.close();
}
}
}
我觉得LZ都弄的乱乱的,都是同一个字段,还弄个A,D,H做什么?直接一个A或就用"业务量"这个字段
如果使用了ClassObj ,就没办法自由了,也就是说添加了字段就不行了
具体的要求,我也不知道LZ的意思,没说清楚
select 业务量,单价,员工编号,经理='',地区='' from 表1
UNION ALL
select 业务量,单价,员工编号,经理='',地区 from 表2
UNION ALL
select 业务量,单价,员工编号,经理,地区='' from 表3";
这样一个SQL语句就出来了
而且没有的字段用空字符串代替了 ""
我老早向他建议过了,一条sql就可以搞定的。他说需求不定,还是用3个sql好
您误会我的意思了,您看分三个SQL写的目的是为了分别为三个结果集加入不同的“组长:XX”字段,像您写的这段代码是有问题的,while(rs.next())已经限制了循环的条件,所以c1.setCaptain("组长:张三")是跑不进来的(不知道是不是这个原因,但是这种写法是跑不起来的),最后我是开了三个 ArrayList<ClassObj>分别装三个SQL结果集,lst,lst2,lst3,然后返回了三个contents,才把三个组长加进去,
static String formatLst(ArrayList<ClassObj> lst) {
String contents = "";
String Band ="组长:张三" //应该有比这个更好的方法,不知道大家能不能想出更好的方法?
for (int i = 0; i < lst.size(); i++) {
contents += Band+"\t"+lst.get(i).getClassBuss() +"\t"+lst.get(i).getClassId() +"\t"+"\n";
}
return contents;
} static String formatLst2(ArrayList<ClassObj> lst2) {
String contents2 = "";
String Band ="组长:李四"
for (int i = 0; i < lst2.size(); i++) {
contents += Band+"\t"+lst2.get(i).getClassBuss() +"\t"+lst2.get(i).getClassId() +"\t"+"\n";
}
return contents2;
}
static String formatLst3(ArrayList<ClassObj> lst3) {
String contents3 = "";
String Band ="组长:王五"
代码重复的很多,但是需求还是满足了,因为三条SQL的组长是不同的,要是用union all装在一起的话,就不好判断分别加入组长了。
String sql = "insert into tbl_report(单价,工号,统计量,日期,导入数据日期)" + "values(?,?,?,?,'nowDate()')";
如果是日期型,就用 "values(?,?,?,?,getdate())"; 不要单引号
呵呵,sql可以加的。不信你试:
select 业务量 as A,单价 as B,员工编号 as C,'组长:张三' as D from 表1;
看看查询结果,是不是D列所有的值都是'组长:张三'
在select语句中,你可以显式的把常量加进去作为查询结果的该列固定值。你把band作为一个参数传进去,就不用写3个方法了
static String formatLst(ArrayList <ClassObj> lst ,String band) {
String contents = "";
// String Band ="组长:张三" //应该有比这个更好的方法,不知道大家能不能想出更好的方法?
for (int i = 0; i < lst.size(); i++) {
contents += band+"\t"+lst.get(i).getClassBuss() +"\t"+lst.get(i).getClassId() +"\t"+"\n";
}
return contents;
}
56525451
首先关于“单价”这一列,其实是下面的结构,
单价
苹果;桔子
桔子;香蕉;西瓜
香蕉;苹果
西瓜
桔子;西瓜单价列其实是产品的名称,有多种产品的之间用“;”隔开,
在代码中用HashMap将名称替换为相应的人为规定的单价,然后在while循环中用split(";")拆分然后计算,
这一步没有问题,
现在要求合计的话,就要在formatLst里将单价(A)和业务量(B)相乘。单价肯定是Double型了,业务量
是count(*)出来的数据,应该用int型,但是运算的时候还是报错了。大家帮忙看看数据类型应当如何
转换,有没有更好的运算方法????
public static void main(String[] args)
{
.........
}
.........
String sql = "select 单价 as A,业务量 as B,员工编号 as C from 表1";
......
String fa = "";
ClassObj c1=null;
while(rs.next()){
fa = rs.getString("A");
c1=new ClassObj();
if(fa.indexOf(";") != -1){
double sum = 0;
String[] temp = fa.split(";");
for(int i = 0 ; i < temp.length; i ++){
sum += getPrice(temp[i]);
}
c1.setClassId(sum);
}else {
c1.setClassId(getPrice(fa));
}
c1.setClassGroup(rs.getString("B"));
c1.setClassNo(rs.getString("C"));
lst.add(c1);
}
private static Map<String,Double> price = new HashMap<String,Double>(0);
static {
price.put("苹果", 1d);
price.put("桔子", 3d);
price.put("香蕉", 2.5);
price.put("西瓜", 1.6);
}
private static double getPrice(String name){
Double d = price.get(name);
return d == null ? 0 : d.doubleValue();
}
static String formatLst(ArrayList<ClassObj> lst) {
String contents = "";
String total = "";
for (int i = 0; i < lst.size(); i++) {
Double hell=lst.get(i).getClassId();//从这开始就范糊涂了,
int song=lst.get(i).getClassGroup();
total = String.valueOf((hell).doubleValue*Integer.parseInt(song)); //???????帮忙解决
contents += lst.get(i).getClassId() +"\t"+lst.get(i).getClassGroup()
+"\t"+ lst.get(i).getClassNo() +"\n";
}
return contents;
}
fa = rs.getString("A");
c1=new ClassObj();
double sum = 0; //提到前面来记录价格
if(fa.indexOf(";") != -1){
String[] temp = fa.split(";");
for(int i = 0 ; i < temp.length; i ++){
sum += getPrice(temp[i]);
}
c1.setClassId(sum);
}else {
sum = getPrice(fa); //只有一个,将价格记录下来
c1.setClassId(getPrice(fa));
}
int amount = 0;
try{
//取得数量并转为int
amount = Integer.parseInt(rs.getString("B"));
}catch(Exception e){
//如果有错,表示rs.getString("B")要么空,要么是无法转换的字符串,那么就不管,此时amount=0;
}
c1.setSong(sum*amount); //看你这里的情况来定,如果合计这个属性在ClassObj里面是double类型,那么就这样。如果是String,那就用 c1.setSong(String.valueOf(sum*amount));
c1.setClassGroup(rs.getString("B"));
c1.setClassNo(rs.getString("C"));
lst.add(c1);
} 下面那个犯糊涂的formatLst里面的计算可以去掉。
现在写import jxl.*;不管用,必须import jxl.WorkbookSettings; 用哪个写哪个,而且文件还要写在src下面。否则就是:软件包 jxl 不存在。
2.代码的灵活性不强,要是向楼上那样要计算单价,合计的话,是不是要写单独的bean和contents??应当如何写??
3.像之前一样要让新数据跟在旧数据后面跑的话,就是true和flase的那个,我在jxl的doc里找了些类似的方法,但好像没成功,不知道是
方法没找对,还是没有if文件是否存在??求解。
我下的是这个jxl包:JExcelAPI的最新版本:jexcelapi_2_6_10.zip
下载地址:http://sourceforge.net/projects/jexcelapi/files/jexcelapi/2.6.10/jexcelapi_2_6_10.zip
class .....
{
public static void writeExcel(String efilePath)throws IOException{
String url = "jdbc:odbc:study11";
String user = "WSuser";
String password = "[email protected]";
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
String sql = "select 业务量 as A,单价 as B,员工编号 as C from 表1";
try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
con = DriverManager.getConnection(url,user,password);
pstmt = con.prepareStatement(sql);
rs = pstmt.executeQuery();
OutputStream outf = new FileOutputStream(efilePath); WritableWorkbook wwb = Workbook.createWorkbook(outf); WritableSheet ws = wwb.createSheet("sheettest", 0);
WritableFont font1 = new WritableFont(WritableFont.TIMES,16,WritableFont.BOLD,false,UnderlineStyle.DOUBLE);
WritableCellFormat format1=new WritableCellFormat(font1);
format1.setAlignment(jxl.format.Alignment.CENTRE);
format1.setBackground(Colour.PINK);
int i=0;
int j=0;
for (int k = 0; k < rs.getMetaData().getColumnCount(); k++) {
ws.addCell(new Label(k,0,rs.getMetaData().getColumnName(k+1),format1));
}
while(rs.next()){
System.out.println(rs.getMetaData().getColumnCount());
for (int k = 0; k < rs.getMetaData().getColumnCount(); k++) {
ws.addCell(new Label(k,j+i+1,rs.getString(k+1)));
} i++;
}
wwb.write();
wwb.close();
} catch (Exception e) {
} finally {
try {
if (rs != null)
rs.close();
if (pstmt != null)
pstmt.close();
if (con != null)
con.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
try {
JExcelOperate.writeExcel("C:\\new_excel.xls");
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
2.因为你的单价列长度不定(就是你的苹果香蕉个数不定,所以只能那么算,你要另外写个方法也可以,在classobj类内部写一个public count 方法,在设置了单价和数量之后再调用一下去计算总计栏,把总计设为classobj的一个属性,然后你的单价的那个Map做成一个静态类的静态成员变量在ClassObj里面可以直接用。
3.jxl应该能够追加,你可以先找到对应的已存在的excel文件的最大行数(jxl应该有相关方法来读excel的),然后写数据的时候从最大数据行的下一行开始写。jxl没用过,具体怎么弄你自己研究一下。
1.我用的是Microsoft SQL Server 2005在建表的时候,‘合计’这一项是要能实现select sum(合计)函数的所以这项的数据类型在没有小数点的情况下是numeric(18, 0),int(我只用过这两个类型)。有小数点的情况就只能用numeric(18, 1),所以我猜测批量写入的方法就不合适了,pstmt.setString(1, c[0]);
pstmt.setString(2, c[1]);
pstmt.setInt(3,Integer.parseInt(c[2]));//如果这项是合计,没有小数的情况是否这样写??
//如果小数,可用setBigDecimal(new BigDecimal(c[2]));具体应该怎么写??这里没明白。请问这种情况应当如何改进代码,没有小数的时候,SQL Server表中应该用那种数据类型??写入的代码
应该怎么改进??有小数点的话pstmt这应该怎么写?
现在就是麻烦问一下,有小数点的具体怎么写???
//如果小数,可用setBigDecimal(new BigDecimal(c[2]));具体应该怎么写??这里没明白。
如果你的字段类型定义为numeric(18, 1)
就用for循环里面不管是带不带小数点,都用setBigDecimal(new BigDecimal(c[2]))
while ((s = br.readLine()) != null) {
if (s.indexOf("合计") > 0) {
continue;
}
String[] c = s.split("\t");
printArray(c);
if (c.length == 3) {
//加入批量参数
pstmt.setString(1, c[0]);
pstmt.setString(2, c[1]);
setBigDecimal(new BigDecimal(c[2])); //是这个意思吗??
pstmt.addBatch();
}
}
另外我要是不建立工程,就只写一个*.java的文本,怎样才能正常导入jar包??
放jdk目录干吗?
如果你是web项目,就放在工程下得lib里面。如果你是cs项目,就应该自己建一个lib目录,然后在执行时classpath把这个lib里面得jar包都包含进来。
如果你就建一个java得文本,那你得到相应目录下去用javac编译,编译得时候指定classpath指向你的jar包位置。
你去看看java得编译过程,网上一堆。