我正在尝试制作一个简单的 servlet 来使用 spring 框架 JdbcDaoSupport 显示数据库中的一些数据。执行一个“SELECT”-sql 命令大约需要 25-35 秒。我对 Spring 还很陌生,我不明白为什么要花这么长时间......
这是我的代码: BeanBox.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd
">
<!-- Data access related beans-->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>Settings.properties</value>
</property>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${db.driverClassName}" />
<property name="url" value="${db.url}" />
<property name="username" value="${db.user}" />
<property name="password" value="${db.password}" />
<property name="initialSize" value="8" />
</bean>
<bean id="productAnalyticsDAO" class="productAnalyticsDAO">
<property name="dataSource" ref="dataSource" />
</bean>
</beans>
products.java(实际的 servlet)
public class products extends HttpServlet {
/**
* Processes requests for both HTTP <code>GET</code> and <code>POST</code>
* methods.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("start:" + System.nanoTime());
response.setContentType("text/html;charset=UTF-8");
ApplicationContext context = new ClassPathXmlApplicationContext("BeanBox.xml");
System.out.println("context created from xml:" + System.nanoTime());
productAnalyticsDAO productDAO = (productAnalyticsDAO) context.getBean("productAnalyticsDAO");
System.out.println("getbean for the DAO:" + System.nanoTime());
String interval = request.getParameterMap().isEmpty()? "today" : request.getParameter("t");
System.out.println("fetch time parameter from request:" + System.nanoTime());
try (PrintWriter out = response.getWriter()) {
/* TODO output your page here. You may use following sample code. */
out.println("<!DOCTYPE html>");
out.println("<html>");
out.println("<head>");
out.println("<title>Servlet products</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>Product analytics : " + interval.toUpperCase() + "</h1>");
out.println("<a href=\"products?t=today\">Today</a>, ");
out.println("<a href=\"products?t=1D\">Yesterday</a>, ");
out.println("<a href=\"products?t=WEEKEND\">Weekend</a>, ");
out.println("<a href=\"products?t=1W\">1 Week</a>, ");
out.println("<a href=\"products?t=1M\">1 Month</a>, ");
out.println("<a href=\"products?t=3M\">3 Month</a>, ");
out.println("<a href=\"products?t=YTD\">Year To Date</a>, ");
out.println("<a href=\"products?t=1Y\">1 Year</a>, ");
out.println("<a href=\"products?t=3Y\">3 Year</a>");
out.println("<table>");
System.out.println("HTML print 1:" + System.nanoTime());
List sales = productDAO.getProducts(interval);
System.out.println("Fetched sqles list:" + System.nanoTime());
for (Iterator iterator = sales.iterator(); iterator.hasNext();) {
out.println("<tr>");
LinkedCaseInsensitiveMap next = (LinkedCaseInsensitiveMap) iterator.next();
out.println("<td>" + next.get("REFERENCE") + "</td>");
out.println("<td>" + next.get("NAME") + "</td>");
out.println("<td>" + next.get("UNITS") + "</td>");
out.println("</tr>");
}
System.out.println("Print data:" + System.nanoTime());
out.println("</table>");
out.println("</body>");
out.println("</html>");
}
}
// <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
/**
* Handles the HTTP <code>GET</code> method.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Handles the HTTP <code>POST</code> method.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Returns a short description of the servlet.
*
* @return a String containing servlet description
*/
@Override
public String getServletInfo() {
return "Short description";
}// </editor-fold>
}
productAnalyticsDAO.java(数据访问对象)
public class productAnalyticsDAO extends JdbcDaoSupport {
public List<String[]> getProducts(String interval){
System.out.println("Entered getProducts:" + System.nanoTime());
String sql = "SELECT PRODUCTS.REFERENCE, "
+ "PRODUCTS.NAME, "
+ "PRODUCTS.CATEGORY, "
+ "SUM(TICKETLINES.UNITS) AS UNITS, "
+ "SUM(TICKETLINES.UNITS * TICKETLINES.PRICE) AS TOTAL "
+ "FROM RECEIPTS, "
+ "TICKETS, "
+ "TICKETLINES, "
+ "PRODUCTS "
+ "WHERE RECEIPTS.ID = TICKETS.ID "
+ "AND TICKETS.ID = TICKETLINES.TICKET "
+ "AND TICKETLINES.PRODUCT = PRODUCTS.ID ";
if(interval.equals("today")){
sql += "AND DATE(RECEIPTS.DATENEW)= CURDATE() ";
}
if(interval.equals("1D")){
sql += "AND DATE_SUB(CURDATE(),INTERVAL 1 DAY) <= DATE(RECEIPTS.DATENEW) ";
}
if(interval.equals("1W")){
sql += "AND DATE_SUB(CURDATE(),INTERVAL 1 WEEK) <= DATE(RECEIPTS.DATENEW) ";
}
if(interval.equals("WEEKEND")){
sql += "AND DATE_SUB(CURDATE(),INTERVAL 1 WEEK) <= DATE(RECEIPTS.DATENEW) ";
sql += "AND DAYOFWEEK(DATE(RECEIPTS.DATENEW))=1 OR DAYOFWEEK(DATE(RECEIPTS.DATENEW))=7 ";
}
if(interval.equals("1M")){
sql += "AND DATE_SUB(CURDATE(),INTERVAL 1 MONTH) <= DATE(RECEIPTS.DATENEW) ";
}
if(interval.equals("3M")){
sql += "AND DATE_SUB(CURDATE(),INTERVAL 3 MONTH) <= DATE(RECEIPTS.DATENEW) ";
}
if(interval.equals("YTD")){
sql += "AND YEAR(RECEIPTS.DATENEW)= YEAR(CURDATE()) <= DATE(RECEIPTS.DATENEW) ";
}
if(interval.equals("1Y")){
sql += "AND DATE_SUB(CURDATE(),INTERVAL 1 YEAR) <= DATE(RECEIPTS.DATENEW) ";
}
if(interval.equals("3Y")){
sql += "AND DATE_SUB(CURDATE(),INTERVAL 3 YEAR) <= DATE(RECEIPTS.DATENEW) ";
}
sql += "AND NOT PRODUCTS.CATEGORY = \"9286649c-00e1-428a-bd45-b47a1e0154b4\" " // filter out ophaal uren
+ "GROUP BY PRODUCTS.CATEGORY, PRODUCTS.NAME "
+ "ORDER BY PRODUCTS.NAME";
System.out.println("Builded SQL string:" + System.nanoTime());
List myBook = getJdbcTemplate().queryForList(sql);
System.out.println("Fetched data:" + System.nanoTime());
return myBook;
}
我使用 System.nanoTime() 来计算不同点之间的弧:
- 从 xml 创建的上下文:4943507136673
- DAO 的 getbean:4943507261046//-> arc : 0.124373 毫秒
- 从请求中获取时间参数:4943507687437//-> arc : 0.426391 毫秒
- HTML print 1:4943507916077//-> arc : 0.228640 毫秒
- 输入 getProducts:4943507993097//-> arc : 0.077020 毫秒
- 构建的 SQL 字符串:4943508103467//-> arc : 0.110370 毫秒
- 已获取数据:4980514095087//-> arc:37005.991620 毫秒
- 获取的sqles列表:4980514152604//-> arc:0.057517毫秒
- 打印数据:4980515844896//-> 弧:1.692292 毫秒
那么,为什么 getJdbcTemplate().queryForList(sql)
速度这么慢......
数据库位于本地主机上,通过 phpMyAdmin 执行 sql 语句要快得多... 显示第 0 - 31 行(总共 32 行,查询花费了 0.1411 秒。)
编辑:执行的最终 SQL 命令为:SELECT PRODUCTS.REFERENCE, PRODUCTS.NAME, PRODUCTS.CATEGORY, SUM(TICKETLINES.UNITS) AS UNITS, SUM(TICKETLINES.UNITS * TICKETLINES.PRICE) AS TOTAL FROM RECEIPTS 、门票、TICKETLINES、产品,其中 RECEIPTS.ID = TICKETS.ID AND TICKETS.ID = TICKETLINES.TICKET AND TICKETLINES.Product = 产品.ID 和日期(RECEIPTS.DATENEW)= CURDATE() 而不是 Products.CATEGORY = "9286649c- 00e1-428a-bd45-b47a1e0154b4"按产品.类别、产品.名称分组 按产品.名称排序
谢谢你, 罗宾
最佳答案
一种可能性是查询的形成可能会减慢结果的速度 查询应该是这样的格式
来自收据 左外联票 收据.ID = 门票.ID 左外联票线路 ON TICKETS.ID = TICKETLINES.TICKET 左外连接产品 ON TICKETLINES.PRODUCT = PRODUCTS.ID
您也可以尝试indexing这些列将使它运行得更快,但在评估后使用它
关于java - JdbcDao支持queryForList慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31623959/