请帮忙优化一下这段代码,请高手一定要帮忙,我会千万分感谢的!

sparadise1003 2009-01-14 04:15:01
这段代码实现的功能为逐层展开产品结构并获得每个对象的信息。产品结构包括产品、部件、零件几个对象,之间关系为:产品包括产品、部件、零件,部件包括部件、零件。根据上述情况,我采用了递归的方法来展开产品结构,现在的问题是,这段代码执行起来非常得慢,查询200条记录需要40秒,我试过了很多解决方法如将查询方法由原来的Statement换成PreparedStatement,之后又将查询写成了存储过程,可是速度都没有明显的提高。请高手指教,这段代码慢在哪里、如何能够快起来?
开发环境:Oracle 8i、JDK1.5

/**
* 此方法用来递归实现展开产品结构的功能
* 其中的LEFT为父结点ID、RIGHT为子结点ID、CLASS2为子结点的表名(需进行表名转化)
*/
public List obtainPartNumber(String leftobid ) {
Connection con = null;
PreparedStatement ps
ResultSet rs = null;
String tableName = "";
String partnumber = "";
String obid = "";

try {

sql = "select /*+RULE*/ CLASS2,RIGHT from PDMM31A.ASSMSTRC where LEFT=?";
ps = con.prepareStatement(sql);
ps.setString(1, leftobid);
rs = ps.executeQuery();

while (rs.next()) {

//进行表名转化,真正的对象信息存放在对应的W2PRODCT(产品)、W2ASSM(部件)等 表中
if (rs.getString("CLASS2").equals("W2ProMtr")) tableName = "W2PRODCT";
if (rs.getString("CLASS2").equals("W2AsmMtr")) tableName = "W2ASSM";
……
string SSql = "select/*+RULE*/ PARTNUMBER from PDMM31A."+ rs.getString("CLASS2") + " where OBID=?";
ps = con.prepareStatement(SSql);
ps.setString(1, rs.getString("RIGHT"));
ResultSet rss = ps.executeQuery();

if (rss.next())
partnumber = rss.getString("PARTNUMBER");

close(rss);
close(ps);

//调用函数obtainPartNumberObjectInfo获取对象信息
obid = obtainPartNumberObjectInfo(partnumber, tableName,con);
/**
*
* 递归调用obtainPartNumber实现逐层展开功能
* <注意>ASSMSTRC表中RIGHT的值是与其CLASS2中的**Mtr表中某个属性的OBID相对应,
* 而表中的LEFT中值是与某个保存对象信息的表中的OBID相对应。
*/
obtainPartNumber(obid, newvalue);

close(rss);
close(ps);
}

} catch (Exception e) {

e.printStackTrace();

} finally {

close(ps);
close(rs);
close(cstmt);

}
return null;

}







public String obtainPartNumberObjectInfo(String partnumber,
String tablename,
connection con

) {

PreparedStatement pss = null;
ResultSet rs = null;
String sql = null;
String obid = "";

try {

sql = "select /*+RULE*/* from PDMM31A." + tablename + " where PARTNUMBER=? ";
pss = con.prepareStatement(sql);
pss.setString(1, partnumber);
rs = pss.executeQuery();


// 计算满足条件的记录数,PARTNUMBEROBJECT_RSCOUNT是个全局变量充当计算器的作用
while (rs.next()) {
PARTNUMBEROBJECT_RSCOUNT++;
}

// 重新执行SQL语句,之前执行的查询操作在统计记录个数时已被用掉
rs = pss.executeQuery();

ArrayList objectArrayList = new ArrayList();// 获得产品结构类中每个属性对象的属性信息

if (rs.next()) {
//获得对象信息,保存在objectArrayList中
if (tablename.equals("W2PRODCT")) {// 产品
//获得产品信息
objectArrayList.add(rs.getString("PARTNUMBER"));// 物料编码
objectArrayList.add("产品");// 类
objectArrayList.add(rs.getString("PROJECTNAME"));// 项目名称
objectArrayList.add(rs.getString("NOMENCLATURE"));// 名称


} else if (tablename.equals("W2ASSM")) {// 部件
//获得部件信息
objectArrayList.add(rs.getString("PARTNUMBER"));
objectArrayList.add("部件");// 类
objectArrayList.add(rs.getString("PROJECTNAME"));
objectArrayList.add(rs.getString("NOMENCLATURE"));


}……

// 将每个物料的属性信息存到 PARTNUMBEROBJECTLIST 中
SearchResultTable o = new SearchResultTable();
o.setResultArrayList(objectArrayList);
PARTNUMBEROBJECTLIST.add(o);

obid = rs.getString("OBID");

}

} catch (Exception e) {

e.printStackTrace();

} finally {

close(pss);
close(rs);
}

return obid;

}

我接Java水平一般般,由于能力有限所以我个人实现想不出更好的优化方法。
请朋友一定要帮帮我,这段代码对我来说很重要,先谢谢了……
...全文
171 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
sparadise1003 2009-01-19
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 OooxiamiooO 的回复:]
使用Hibernate框架帮你解决效率问题吧,算法就没必要使用递归了,使用循环套循环就可以了,具体的层次结构可以写一个xml配置文件来实现。这样算法会比递归快很多倍
[/Quote]

OooxiamiooO 说的方法我没用过,大家帮我分析一下看看这种方法可行吗,或者还有什么更好的方法?
sparadise1003 2009-01-19
  • 打赏
  • 举报
回复
说白了,我想实现的功能就是遍历一棵树并获得每个节点的信息,实现这个功能用什么方法最快?
sparadise1003 2009-01-19
  • 打赏
  • 举报
回复
谢谢朋友们的参与,等了好几天也没等到java2000_net专家的回复,不等了,结贴洒分!
OooxiamiooO 2009-01-17
  • 打赏
  • 举报
回复
使用Hibernate框架帮你解决效率问题吧,算法就没必要使用递归了,使用循环套循环就可以了,具体的层次结构可以写一个xml配置文件来实现。这样算法会比递归快很多倍
danengnai__ 2009-01-17
  • 打赏
  • 举报
回复
依我看就是思路的问题

做的是树吗,如果是的话就做成延迟加载的吧
sparadise1003 2009-01-16
  • 打赏
  • 举报
回复
数据库中的表数据时不太大,一般的表几千条数据,PDMM31A.ASSMSTRC表有几万条数据吧,我也建了索引啊!
yehong_sky 2009-01-16
  • 打赏
  • 举报
回复
把数据库链接 封装成一类...你那样只要写一个方法就要写一个链接,频繁的重复没意义..
酒剑仙 2009-01-16
  • 打赏
  • 举报
回复
楼主 先看下数据库的数据量,再检查下数据库建立索引没有?
JAVA不是万能的。如果你数据量比较大,而且数据库没有索引,JAVA根本不可能运行的快。因为他要等数据库运行出结果的嘛
sparadise1003 2009-01-16
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 dengjianqiang001 的回复:]
我空间里有很多JAVA资料 ,欢迎下载交流。
[/Quote]
晕,不带做广告的啊?
各位帮帮忙,看看我的代码为什么这么慢?有什么什么解决的方案?在线等
sparadise1003 2009-01-16
  • 打赏
  • 举报
回复
我的需求:逐层展开产品结构,并获得每个结点的信息,我所说的产品结构和资源管理器结构类似,换一种描述方式就是:实现遍厉某个磁盘并获得其下的文件夹和文件信息。我就想实现这样的功能,我现在用的是递归实现逐层展开功能,可是这样效率很低,不知道有没有更高效的方法呢?
waveletsoft 2009-01-16
  • 打赏
  • 举报
回复
如果存储过程都慢,你在怎么改java那都是没用的。。。

qianqian51267 2009-01-14
  • 打赏
  • 举报
回复
我觉的你慢的根本原因出在了你的数据库设计上

你循环递归访问数据库不可能不慢啊,你把你想要的结果

还有需求说下吧,我觉的重新设计一下比较好。
sparadise1003 2009-01-14
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 xuhaiyang 的回复:]
在Java里递归查询效率肯定不会高的。你再好好看看需求找个更好的实现方式吧
[/Quote]
我用递归想实现的功能是逐层展开产品结构,我所说的产品结构和资源管理器结构类似,“产品”就相当于某个磁盘、“部件”就相当于一个文件夹、“零件”就相当于一个文件。如果我想实现遍厉某个磁盘并获得其下的文件夹和文件信息,应该样做效率最高啊?我只能想到用递归的方法了……
sparadise1003 2009-01-14
  • 打赏
  • 举报
回复
我把Connection改为参数传进来,可速度没有什么变化,希望高手朋友帮忙分析一下,慢的原因和优化方案?
改后的代码:

/**
* 此方法用来递归实现展开产品结构的功能
* 其中的LEFT为父结点ID、RIGHT为子结点ID、CLASS2为子结点的表名(需进行表名转化)
*/
public List obtainPartNumber(String leftobid ,Connection con ) {
PreparedStatement ps
ResultSet rs = null;
String tableName = "";
String partnumber = "";
String obid = "";

try {

sql = "select /*+RULE*/ CLASS2,RIGHT from PDMM31A.ASSMSTRC where LEFT=?";
ps = con.prepareStatement(sql);
ps.setString(1, leftobid);
rs = ps.executeQuery();

while (rs.next()) {

//进行表名转化,真正的对象信息存放在对应的W2PRODCT(产品)、W2ASSM(部件)等 表中
if (rs.getString("CLASS2").equals("W2ProMtr")) tableName = "W2PRODCT";
if (rs.getString("CLASS2").equals("W2AsmMtr")) tableName = "W2ASSM";
……
string SSql = "select/*+RULE*/ PARTNUMBER from PDMM31A."+ rs.getString("CLASS2") + " where OBID=?";
ps = con.prepareStatement(SSql);
ps.setString(1, rs.getString("RIGHT"));
ResultSet rss = ps.executeQuery();

if (rss.next())
partnumber = rss.getString("PARTNUMBER");

close(rss);
close(ps);

//调用函数obtainPartNumberObjectInfo获取对象信息
obid = obtainPartNumberObjectInfo(partnumber, tableName,con);
/**
*
* 递归调用obtainPartNumber实现逐层展开功能
* <注意>ASSMSTRC表中RIGHT的值是与其CLASS2中的**Mtr表中某个属性的OBID相对应,
* 而表中的LEFT中值是与某个保存对象信息的表中的OBID相对应。
*/
obtainPartNumber(obid, newvalue);

close(rss);
close(ps);
}

} catch (Exception e) {

e.printStackTrace();

} finally {

close(ps);
close(rs);
close(cstmt);

}
return null;

}







public String obtainPartNumberObjectInfo(String partnumber,
String tablename,
connection con

) {

PreparedStatement pss = null;
ResultSet rs = null;
String sql = null;
String obid = "";

try {

sql = "select /*+RULE*/* from PDMM31A." + tablename + " where PARTNUMBER=? ";
pss = con.prepareStatement(sql);
pss.setString(1, partnumber);
rs = pss.executeQuery();


// 计算满足条件的记录数,PARTNUMBEROBJECT_RSCOUNT是个全局变量充当计算器的作用
while (rs.next()) {
PARTNUMBEROBJECT_RSCOUNT++;
}

// 重新执行SQL语句,之前执行的查询操作在统计记录个数时已被用掉
rs = pss.executeQuery();

ArrayList objectArrayList = new ArrayList();// 获得产品结构类中每个属性对象的属性信息

if (rs.next()) {
//获得对象信息,保存在objectArrayList中
if (tablename.equals("W2PRODCT")) {// 产品
//获得产品信息
objectArrayList.add(rs.getString("PARTNUMBER"));// 物料编码
objectArrayList.add("产品");// 类
objectArrayList.add(rs.getString("PROJECTNAME"));// 项目名称
objectArrayList.add(rs.getString("NOMENCLATURE"));// 名称


} else if (tablename.equals("W2ASSM")) {// 部件
//获得部件信息
objectArrayList.add(rs.getString("PARTNUMBER"));
objectArrayList.add("部件");// 类
objectArrayList.add(rs.getString("PROJECTNAME"));
objectArrayList.add(rs.getString("NOMENCLATURE"));


}……

// 将每个物料的属性信息存到 PARTNUMBEROBJECTLIST 中
SearchResultTable o = new SearchResultTable();
o.setResultArrayList(objectArrayList);
PARTNUMBEROBJECTLIST.add(o);

obid = rs.getString("OBID");

}

} catch (Exception e) {

e.printStackTrace();

} finally {

close(pss);
close(rs);
}

return obid;

}


xuhaiyang 2009-01-14
  • 打赏
  • 举报
回复
在Java里递归查询效率肯定不会高的。你再好好看看需求找个更好的实现方式吧
lihan6415151528 2009-01-14
  • 打赏
  • 举报
回复
可能帮你全部优化是不太现实的,在这里只能给你说思路,你自己取修改了
fulianglove 2009-01-14
  • 打赏
  • 举报
回复
封装obtainPartNumber,再写一个方法A,在A里调用obtainPartNumber,connection在A里构建,
然后把这个connection作为参数传递给obtainPartNumber,避免在低轨操作中对connection频繁的创建,销毁。
看看能不能有所提高
lanrenjun_java 2009-01-14
  • 打赏
  • 举报
回复
数据库打开关闭太频繁 递归的时候Connection con = null;
建议把获取连接写在外面 避免频繁操作Connection

67,516

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧