前年给地图
技术审查中心做了一个培训的报名系统,功能需求比较简单,由于当时刚开始摸索
java就只能照葫芦画瓢的使用JDBC写的程序。这是中百信公司的遗留项目,我接手过来的,仿照以前的代码写得。
出现问题的代码:
[html]
<div id="content">
<div class="locbackground">
</div>
<div class="text">
<center>
<h1>
查看培训(会议)报名信息
</h1>
<div><input type="button" value="导出会议(培训)报名信息 "cid")%>'"/></div>
<br/><table class="listCases" width="100%" border="0"
style="width: 100%; FONT-SIZE: 18px;
word-break: break-all"
cellspacing="1" cellpadding="5" bgcolor=#455ca2>
<thead>
<tr height="40px">
<th width="70" bgcolor=#dcdcdc align="center" class=""
style="font-size: 14px; FONT-WEIGHT: bold">
操作
</th>
<th width="30" bgcolor=#dcdcdc align="center" class=""
style="font-size: 14px; FONT-WEIGHT: bold">
序号
</th>
<th width="30" bgcolor=#dcdcdc align="center" class=""
style="font-size: 14px; FONT-WEIGHT: bold">
姓名
</th>
<th bgcolor=#dcdcdc align="center" class=""
style="font-size: 14px; FONT-WEIGHT: bold">
性别
</th>
<th bgcolor=#dcdcdc align="center" class=""
style="font-size: 14px; FONT-WEIGHT: bold">
民族
</th>
<th bgcolor=#dcdcdc align="center" class=""
style="font-size: 14px; FONT-WEIGHT: bold">
身份证号
</th>
<th bgcolor=#dcdcdc align="center" class=""
style="font-size: 14px; FONT-WEIGHT: bold">
工作单位
</th>
<th bgcolor=#dcdcdc align="center" class=""
style="font-size: 14px; FONT-WEIGHT: bold">
职务(职称)
</th>
<th bgcolor=#dcdcdc align="center" class=""
style="font-size: 14px; FONT-WEIGHT: bold">
手机号码
</th>
<th bgcolor=#dcdcdc align="center" class=""
style="font-size: 14px; FONT-WEIGHT: bold">
乘坐何种 交通工具(班次)
</th>
<th bgcolor=#dcdcdc align="center" class=""
style="font-size: 14px; FONT-WEIGHT: bold">
到达时间
</th>
<th bgcolor=#dcdcdc align="center" class=""
style="font-size: 14px; FONT-WEIGHT: bold">
注册时间
</th>
<th bgcolor=#dcdcdc align="center" class=""
style="font-size: 14px; FONT-WEIGHT: bold">
ip地址
</th>
</tr>
</thead>
<%
Collection registerId = conferenceRegisterAssignOp.getRegisterIdByConferenceId(Integer.parseInt(request.getParameter("cid")));
Iterator it = registerId.iterator();
int index = 1;
while (it.hasNext()) {
Integer integer = (Integer)it.next();
int rid = integer.intValue();
Register temp = registerOp.getCaseInfo(rid);
%>
<tr>
<td class="listContent">
<a href="dtsc/pxbm/editRegister.jsp?registerId=<%=temp.getId()%>">编辑</a>
<br />
<br />
<a href="dtsc/pxbm/deleteRegister.jsp?registerId=<%=temp.getId()%>">删除</a>
<br />
<br />
<a href="dtsc/pxbm/editRegister.jsp?registerId=<%=temp.getId()%>">查看详细</a>
</td>
<td class="listContent"><%=index%></td>
<td class="listContent"><%=temp.getName() %></td>
<td class="listContent"><%=CodeSet.getSex(temp.getSex())%></td>
<td class="listContent"><%=temp.getRace()%></td>
<td class="listContent"><%=temp.getIdentificationId() %></td>
<td class="listContent"><%=temp.getDepartment()%></td>
<td class="listContent"><%=temp.getPositionOrIdentity()%></td>
<td class="listContent"><%=temp.getMobilephone()%></td>
<td class="listContent"><%=temp.getDeparture()%></td>
<td class="listContent"><%=temp.getArrivingTime()%></td>
<td class="listContent"><%=temp.getRegisterTime()%></td>
<td class="listContent"><%=temp.getIp()%></td>
</tr>
<%
++index;
}
%>
</table>
</center>
</div>
</div>
因为是嵌在JSP页面的中代码,在
java代码后面跟的是一些显示用的HTML代码。
注意这一段代码:
[
javascript]
Collection registerId = conferenceRegisterAssignOp.getRegisterIdByConferenceId(Integer.parseInt(request.getParameter("cid")));
Iterator it = registerId.iterator();
int index = 1;
while (it.hasNext()) {
Integer integer = (Integer)it.next();
int rid = integer.intValue();
Register temp = registerOp.getCaseInfo(rid);
这里边先根据cid(培训会议表id)取到了参加本次会议的注册人员的id列表。
[
javascript]
<pre name="code" class="
java">Collection registerId = conferenceRegisterAssignOp.getRegisterIdByConferenceId(Integer.parseInt(request.getParameter("cid")));
然后再遍历这个列表,对每一个注册人员id,都取出这个人员的详细信息。
[
java]
Register temp = registerOp.getCaseInfo(rid);
这样在报名的数量达到200条的时候运行起来的时间大约为40s到70秒s。由于这个页面的table中的行tr是在后台逐条生成的,再Collection遍历是陆陆续续发送到浏览器的,这样会使浏览器等待页面的时间太长,导致浏览器与后台
web Server的连接超过TimeOut时长,断开连接。反应到前端浏览器的现象就是页面的前半部分加载完成,列表没有全部加载出来。
改进的代码:
原因分析清楚之后,我们需要改进这个查找机制,需要把这两次操作合并到一次SQL查询中完成,让SQL在后台一次就把我们需要的注册人员的详细信息查询出来。
[
java]
Collection registers = conferenceRegisterAssignOp.getRegistersByConferenceId(Integer.parseInt(request.getParameter("cid")));
Iterator it = registers.iterator();
int index = 1;
while (it.hasNext()) {
Register temp = (Register)it.next();
在这里,我只用了一次查询:
[
java]
getRegistersByConferenceId就取出来了所有的注册信息。这个函数是这样写的:
[
java]
<pre name="code" class="
java">//根据会议Id获得参加会议的报名情况
public Collection<Register> getRegistersByConferenceId(int conferenceId) throws Exception
{
Statement stmt=con.createStatement();
ResultSet rst=stmt.executeQuery("SELECT dtsc_register.id, dtsc_register.name, dtsc_register.sex, dtsc_register.age, dtsc_register.race,"+
"dtsc_register.identificationId, dtsc_register.department, dtsc_register.positionOrIdentity, dtsc_register.mobilephone,"+
"dtsc_register.departure, dtsc_register.arrivingTime, dtsc_register.ip, dtsc_register.registerTime, dtsc_register.education,"+
"dtsc_register.address, dtsc_register.zipcode, dtsc_register.suozaibumen, dtsc_register.telephone, dtsc_register.isFirst "+
"FROM dtsc_conferenceRegisterAssign INNER JOIN "+
"dtsc_register ON dtsc_conferenceRegisterAssign.registerId = dtsc_register.id "+
"WHERE dtsc_conferenceRegisterAssign.conferenceId = "+conferenceId+" ORDER BY dtsc_conferenceRegisterAssign.id");
Collection<Register> registers = new ArrayList<Register>();
while (rst.next()) {
Register register=new Register();
register.setId(rst.getInt("id"));
register.setName(rst.getString("name"));
register.setSex(rst.getInt("sex"));
register.setRace(rst.getString("race"));
register.setIdentificationId(rst.getString("identificationId"));
register.setDepartment(rst.getString("department"));
register.setPositionOrIdentity(rst.getString("positionOrIdentity"));
register.setMobilephone(rst.getString("mobilephone"));
register.setDeparture(rst.getString("departure"));
register.setArrivingTime(rst.getString("arrivingTime"));
register.setIp(rst.getString("ip"));
register.setRegisterTime(rst.getString("registerTime"));
register.setEducation(rst.getString("education"));
register.setAddress(rst.getString("address"));
register.setZipcode(rst.getString("zipcode"));
register.setSuozaibumen(rst.getString("suozaibumen"));
register.setTelephone(rst.getString("telephone"));
register.setIsFirst(rst.getInt("isFirst"));
registers.add(register);
}
con.close();
return registers;
}
通过INNER JOIN就可以通过一次数据库的查询达到目的。
结论:
对比前后两种代码,我们看到,对
数据库的操作次数越少越好。如前面我们总共进行了<本次会议报名人数+1>次
数据库查询,后着我们只进行了一次Inner Join查询操作。差距显而易见。所以在表之间靠外键进行联系时,如果你用原始的JDBC语句,请一次完成查询。
如果你使用的是HIbernate这样的ORM框架,那么恭喜你,你不用为构造复杂的SQL而操心,她内部的多层缓存机制和Lazy懒惰机制会使你最少的进行
数据库查询(当然你需要了解更多的配置才行),大大提高效率。