day15 分頁及 JDBC 大數據的處理

Author:相忠良
Email: ugoood@163.com
起始於:June 7, 2018
最後更新日期:June 8, 2018javascript

聲明:本筆記依據傳智播客方立勳老師 Java Web 的授課視頻內容記錄而成,中間加入了本身的理解。本筆記目的是強化本身學習所用。如有疏漏或不當之處,請在評論區指出。謝謝。
涉及的圖片,文檔寫完後,一次性更新。css

本節案例是承接 day14 的客戶關係管理系統,繼續改造。html

1. 分頁實現(重點)

所需小知識,以下:
select id,name from customer limit 0,5;顯示第1-5條數據,第1頁;
select id,name from customer limit 5,5;顯示第6-10條數據,第2頁;
select id,name from customer limit 10,5;顯示第11-15條數據,第3頁。java

分頁結構圖以下(重要的就是這個圖,後面的工做均圍繞這個圖展開):mysql

1

上圖涉及了3個封裝數據的 javabean,先實現了他們!以下:web

cn.wk.domain.PageBeansql

package cn.wk.domain;

import java.util.List;

public class PageBean {
    private List list;
    private int totalrecord;
    private int pagesize;
    private int totalpage;
    private int currentpage;
    private int previouspage;
    private int nextpage;
    private int[] pagebar;

    public int getPagesize() {
        return pagesize;
    }

    public void setPagesize(int pagesize) {
        this.pagesize = pagesize;
    }

    public List getList() {
        return list;
    }

    public void setList(List list) {
        this.list = list;
    }

    public int getTotalrecord() {
        return totalrecord;
    }

    public void setTotalrecord(int totalrecord) {
        this.totalrecord = totalrecord;
    }

    public int getTotalpage() {
        if (this.totalrecord % this.pagesize == 0)
            this.totalpage = this.totalrecord / this.pagesize;
        else
            this.totalpage = this.totalrecord / this.pagesize + 1;
        return totalpage;
    }

    public int getCurrentpage() {
        return currentpage;
    }

    public void setCurrentpage(int currentpage) {
        this.currentpage = currentpage;
    }

    public int getPreviouspage() {
        if (this.currentpage - 1 < 1)
            this.previouspage = 1;
        else
            this.previouspage = this.currentpage - 1;
        return previouspage;
    }

    public int getNextpage() {
        if (this.currentpage + 1 >= this.totalpage)
            this.nextpage = this.totalpage;
        else
            this.nextpage = this.currentpage + 1;
        return nextpage;
    }

    public int[] getPagebar() {
        int startpage;
        int endpage;
        int pagebar[] = null;
        if (this.totalpage <= 10) {
            pagebar = new int[this.totalpage];
            startpage = 1;
            endpage = this.totalpage;
        } else {
            pagebar = new int[10];
            startpage = this.currentpage - 4;
            endpage = this.currentpage + 5;

            if (startpage < 1) {
                startpage = 1;
                endpage = 10;
            }

            if (endpage > this.totalpage) {
                endpage = this.totalpage;
                startpage = this.totalpage - 9;
            }
        }

        int index = 0;
        for (int i = startpage; i <= endpage; i++) {
            pagebar[index++] = i;
        }
        this.pagebar = pagebar;
        return this.pagebar;
    }
}

cn.wk.domain.QueryInfo數據庫

package cn.wk.domain;

public class QueryInfo {
    private int currentpage = 1; // 用戶要看的頁
    private int pagesize = 5;    // 用戶想看的頁面大小
    private int startindex;      // 記住用戶看的頁的數據在數據庫的起始位置

    public int getCurrentpage() {return currentpage;}
    public void setCurrentpage(int currentpage) {
        this.currentpage = currentpage;
    }
    public int getPagesize() {return pagesize;}
    public void setPagesize(int pagesize) {this.pagesize = pagesize;}
    public int getStartindex() {
        this.startindex = (this.currentpage - 1) * this.pagesize;
        return startindex;
    }
}

cn.wk.domain.QueryResultoracle

package cn.wk.domain;

import java.util.List;

public class QueryResult {
    private List list;       // 記住用戶看的頁的數據
    private int totalrecord; // 記住總記錄數

    public List getList() {return list;}
    public void setList(List list) {this.list = list;}
    public int getTotalrecord() {return totalrecord;}
    public void setTotalrecord(int totalrecord) {
        this.totalrecord = totalrecord;
    }
}

cn.wk.dao.impl.CustomerDaoImpl添加1個方法(同時將該方法聲明加入cn.wk.dao.CustomerDao接口中),以下:app

/* 爲分頁功能 所添加的代碼 */
// 獲取頁面數據和總記錄數
public QueryResult pageQuery(int startindex, int pagesize) {

  Connection conn = null;
  PreparedStatement st = null;
  ResultSet rs = null;

  QueryResult qr = new QueryResult();

  try {
    conn = JdbcUtils.getConnection();
    String sql = "select * from customer limit ?,?";
    st = conn.prepareStatement(sql);
    st.setInt(1, startindex);
    st.setInt(2, pagesize);
    rs = st.executeQuery();
    List list = new ArrayList();
    while (rs.next()) {
      Customer c = new Customer();
      c.setBirthday(rs.getDate("birthday"));
      c.setCellphone(rs.getString("cellphone"));
      c.setDescription(rs.getString("description"));
      c.setEmail(rs.getString("email"));
      c.setGender(rs.getString("gender"));
      c.setId(rs.getString("id"));
      c.setName(rs.getString("name"));
      c.setPreference(rs.getString("preference"));
      c.setType(rs.getString("type"));
      list.add(c);
    }
    qr.setList(list);

    // 總記錄數
    sql = "select count(*) from customer";
    st = conn.prepareStatement(sql);
    rs = st.executeQuery();
    if (rs.next()) {
      qr.setTotalrecord(rs.getInt(1));
    }
    return qr;
  } catch (Exception e) {
    throw new DaoException(e);
  } finally {
    JdbcUtils.release(conn, st, rs);
  }
}

修改cn.wk.service.impl.BusinessServiceImpl,向其添加下面的方法(同時將該方法聲明加入cn.wk.service.BusinessService接口中),以下:

public PageBean pageQuery(QueryInfo queryInfo) {
  // 調用 dao 獲取頁面數據
  QueryResult qr = dao.pageQuery(queryInfo.getStartindex(),
      queryInfo.getPagesize());

  // 根據 dao 查詢結果,生成頁面顯示所需的 pagebean
  PageBean bean = new PageBean();
  bean.setCurrentpage(queryInfo.getCurrentpage());
  bean.setList(qr.getList());
  bean.setPagesize(queryInfo.getPagesize());
  bean.setTotalrecord(qr.getTotalrecord());
  return bean;
}

修改cn.wk.web.controller.ListCustomerServlet以下:

package cn.wk.web.controller;

import java.io.IOException;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.wk.domain.PageBean;
import cn.wk.domain.QueryInfo;
import cn.wk.service.BusinessService;
import cn.wk.service.impl.BusinessServiceImpl;
import cn.wk.utils.WebUtils;

// 用分頁技術,獲得全部客戶顯示
public class ListCustomerServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        try {
            // 把 request 信息封裝成 查詢信息 bean 中
            QueryInfo info = WebUtils.request2Bean(req, QueryInfo.class);
            BusinessService service = new BusinessServiceImpl();
            PageBean pagebean = service.pageQuery(info);
            req.setAttribute("pagebean", pagebean);
            req.getRequestDispatcher("/WEB-INF/jsp/listcustomer.jsp").forward(
                    req, resp);
        } catch (Exception e) {
            e.printStackTrace();
            req.setAttribute("message", "查看客戶失敗!!");
            req.getRequestDispatcher("/message.jsp").forward(req, resp);
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        doGet(req, resp);
    }
}

最後,修改/WEB-INF/jsp/listcustomer.jsp(改爲分頁顯示,而不是所有顯示)以下:
<%@ taglib uri="/wk" prefix="wk"%>在 1.1 節有定義。

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="/wk" prefix="wk"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">

<head>
<title>列出全部客戶</title>

<style type="text/css">
    .even{background-color:#FFFFCC}
    .odd{background-color:#CCFFFF}
    tr:hover{background-color:#FFCCCC}
</style>
</head>

<body style="text-align: center;">
    <table frame="border" width="85%">
        <tr>
            <td>客戶姓名</td>
            <td>性別</td>
            <td>生日</td>
            <td>手機</td>
            <td>郵箱</td>
            <td>愛好</td>
            <td>類型</td>
            <td>備註</td>
            <td>操做</td>
        </tr>

        <c:forEach var="c" items="#{requestScope.pagebean.list}" varStatus="status">
            <tr class="${status.count%2==0?'even':'odd'}">
                <td>${c.name }</td>
                <td>${c.gender }</td>
                <td>${c.birthday }</td>
                <td>${c.cellphone }</td>
                <td>${c.email }</td>
                <td>${wk:sub(c.preference) }</td>
                <td>${c.type }</td>
                <td>${wk:sub(c.description) }</td>
                <td>
                    <a href="${pageContext.request.contextPath}/servlet/EditCustomerServlet?id=${c.id}">修改</a>
                    <a href="javascript:void(0)" onclick="del(${c.id})">刪除</a>
                    <!-- <a href="javascript:void(0)" onclick="del('${c.id}')">刪除</a>  加單引號才能刪,怕數據被別人刪,因此註釋掉 -->
                </td>
            </tr>
        </c:forEach>
    </table>
    <br />

    <script type="text/javascript">
        function del(id){
            if(window.confirm("您肯定刪除??")){
                window.location.href='${pageContext.request.contextPath}/servlet/DelCustomerServlet?id=' + id;
            }
        }

        function gotopage(currentpage) {
            if (currentpage < 1 || currentpage != parseInt(currentpage)
                    || currentpage > ${pagebean.totalpage}) {
                alert("請輸入有效值!!");
                document.getElementById("pagenum").value = '';
            } else {
                var pagesize = document.getElementById("pagesize").value;
                window.location.href = '${pageContext.request.contextPath}/servlet/ListCustomerServlet?currentpage='
                        + currentpage + '&pagesize=' + pagesize;
            }
        }
    </script>

    共[${pagebean.totalrecord}]條記錄,
    每頁
    <input type="text" id="pagesize" value="${pagebean.pagesize}"
        onchange="gotopage(${pagebean.currentpage})" style="width:30px"
        maxlength="2">條,
     共[${pagebean.totalpage}]頁,
    當前第[${pagebean.currentpage}]頁 &nbsp;&nbsp;&nbsp;

    <a href="javascript:void(0)"
        onclick="gotopage(${pagebean.previouspage})">上一頁</a>

    <c:forEach var="pagenum" items="${pagebean.pagebar}">
        <c:if test="${pagenum==pagebean.currentpage }">
            <font color="red">${pagenum}</font>
        </c:if>

        <c:if test="${pagenum!=pagebean.currentpage }">
            <a href="javascript:void(0)" onclick="gotopage(${pagenum})">${pagenum}</a>
        </c:if>
    </c:forEach>

    <a href="javascript:void(0)" onclick="gotopage(${pagebean.nextpage})">下一頁</a>

    <input type="text" id="pagenum" style="width:35px" >
    <input type="button" value=" GO " onclick="gotopage(document.getElementById('pagenum').value)">

</body>
</html>

1.1 自建 EL 表達式去處理簡介過長問題

cn.wk.utils.MyEL,注意 EL 需創建靜態方法,代碼以下:

package cn.wk.utils;

public class MyEL {
    public static String sub(String str) {
        if (str.length() > 10)
            return str.substring(0, 10) + "......";
        return str;
    }
}

再寫一個tld文件,\WEB-INF\wk.tld

<?xml version="1.0" encoding="UTF-8" ?>

<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
  version="2.0">

  <description>JSTL 1.1 functions library</description>
  <display-name>JSTL functions</display-name>
  <tlib-version>1.1</tlib-version>
  <short-name>fn</short-name>
  <uri>/wk</uri>

   <function>
    <name>sub</name>
    <function-class>cn.wk.utils.MyEL</function-class>
    <function-signature>java.lang.String sub(java.lang.String)</function-signature>
  </function>

</taglib>

2. 完成客戶關係管理案例

修改客戶信息的cn.wk.web.controller.EditCustomerServlet

package cn.wk.web.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.wk.domain.Customer;
import cn.wk.service.BusinessService;
import cn.wk.service.impl.BusinessServiceImpl;
import cn.wk.utils.Globals;
import cn.wk.utils.WebUtils;

public class EditCustomerServlet extends HttpServlet {

    // 根據id獲取要修改的客戶信息
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        String id = req.getParameter("id");
        BusinessService service = new BusinessServiceImpl();
        Customer c = service.findCustomer(id);

        req.setAttribute("genders", Globals.genders);
        req.setAttribute("preferences", Globals.preferences);
        req.setAttribute("types", Globals.types);

        req.setAttribute("c", c);
        req.getRequestDispatcher("/WEB-INF/jsp/editcustomer.jsp").forward(req,
                resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {

        req.setCharacterEncoding("UTF-8");
        // 把填寫的表單修改信息封裝到 customer 對象中
        try {
            Customer c = WebUtils.request2Bean(req, Customer.class); // 裏面有id
            BusinessService service = new BusinessServiceImpl();
            service.updateCustomer(c);
            req.setAttribute("message", "更新成功!!");
        } catch (Exception e) {
            e.printStackTrace();
            req.setAttribute("message", "更新失敗!!");
        }
        req.getRequestDispatcher("/message.jsp").forward(req, resp);
    }
}

/WEB-INF/jsp/editcustomer.jsp以下(涉及數據回顯):

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>修改用戶的視圖</title>
    <script type="text/javascript" src="${pageContext.request.contextPath }/js/ShowCalendar.js"></script>
    <script type="text/javascript">
        function makepre(){
            var pres = document.getElementsByName("pre");
            var preference = "";
            for(var i = 0; i < pres.length; i++){
                var input = pres[i];
                if(input.checked==true){
                    preference = preference + input.value + ",";
                }
            }
            // 組裝字符串   跳舞,打麻將,看鳳姐
            preference = preference.substr(0, preference.length - 1);

            var form = document.getElementById("form");
            var input = document.createElement("input");
            input.type = "hidden";
            input.name = "preference";
            input.value = preference;

            form.appendChild(input);
            return true;
        }
    </script>
  </head>

<body style="text-align:center;">
    <br />
    <form id="form"
        action="${pageContext.request.contextPath}/servlet/EditCustomerServlet"
        method="post" onsubmit="return makepre()">
        <!-- js代碼,當按submit按鈕時,就調用makepre()方法 -->

        <table border="1" width="30%">
            <input type="hidden" name="id" value="${c.id}">
            <tr>
                <td>客戶姓名</td>
                <td><input type="text" name="name" value="${c.name}"></td>
            </tr>

            <tr>
                <td>性別</td>
                <td><c:forEach var="gender" items="${genders}">
                        <input type="radio" name="gender" value="${gender}" ${c.gender==gender?'checked':'' }> ${gender}
                </c:forEach></td>
            </tr>

            <tr>
                <td>生日</td>
                <td><input type="text" name="birthday"
                    onClick="showCalendar(this.id)" id="birthday" value="${c.birthday}"></td>
            </tr>

            <tr>
                <td>手機</td>
                <td><input type="text" name="cellphone" value="${c.cellphone}"></td>
            </tr>

            <tr>
                <td>郵箱</td>
                <td><input type="text" name="email" value="${c.email}"></td>
            </tr>

            <tr>
                <td>愛好</td>
                <td><c:forEach var="p" items="${preferences}">
                        <input type="checkbox" name="pre" value="${p}" ${fn:contains(c.preference,p)?'checked':'' }>${p}
                </c:forEach></td>
            </tr>

            <tr>
                <td>客戶類型</td>
                <td><c:forEach var="t" items="${types}">
                        <input type="radio" name="type" value="${t}" ${c.type==t?'checked':''}>${t}
                </c:forEach></td>
            </tr>

            <tr>
                <td>客戶備註</td>
                <td>
                <textarea rows="5" cols="100" name="description">${c.description}</textarea>
                </td>
            </tr>

            <tr>
                <td><input type="reset" value="重置"></td>
                <td><input type="submit" value="修改客戶"></td>
            </tr>
        </table>
    </form>
</body>
</html>

刪除客戶數據的cn.wk.web.controller.DelCustomerServlet

package cn.wk.web.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.wk.service.BusinessService;
import cn.wk.service.impl.BusinessServiceImpl;

// 刪除記錄
public class DelCustomerServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        try {
            String id = req.getParameter("id");
            BusinessService service = new BusinessServiceImpl();
            service.deleteCustomer(id);
            req.setAttribute("message", "刪除成功!!");
        } catch (Exception e) {
            e.printStackTrace();
            req.setAttribute("message", "刪除失敗!!");
        }
        req.getRequestDispatcher("/message.jsp").forward(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        doGet(req, resp);
    }
}

3. jdbc 大數據的處理

準備:新建 java 工程,名字爲 day15。

這裏的大數據 LOB(Large Objects) 僅僅指:

  • clob 用於存大文本,Text;
  • blob 用於存二進制數據,如圖像,聲音,二進制文件等。

對MySQL而言只有blob,而沒有clob,mysql存儲大文本採用的是Text,Text和blob分別又分爲:

  • TINYTEXT、TEXT、MEDIUMTEXT和LONGTEXT
  • TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB

對於MySQL中的Text類型,可調用以下方法去存:

// 給個reader流,而不能給String,大數據的處理只能經過流
PreparedStatement.setCharacterStream(index, reader, length);
//注意length長度須設置,而且設置爲int型

對MySQL中的Text類型,可調用以下方法獲取:

reader = resultSet. getCharacterStream(i);
reader = resultSet.getClob(i).getCharacterStream();
string s = resultSet.getString(i);

例子 Demo1:
前提是準備好 資源文件db.properties,1.txt,mysql-connector-java-5.0.8-bin.jar,建立好day15數據庫和 testclob 表(在下面代碼裏有),而後在作這個實驗。

public class Demo1 {

    /**
     * 讀寫大文本     *
     * create table testclob ( id varchar(40) primary key, resume text );
     * */

    @Test
    public void insert() throws SQLException, FileNotFoundException {
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection();
            String sql = "insert into testclob(id,resume) values(?,?)";
            st = conn.prepareStatement(sql);
            st.setString(1, "1");

            File file = new File("src/1.txt");
            FileReader reader = new FileReader(file);
            st.setCharacterStream(2, reader, (int) file.length());
            int num = st.executeUpdate();
            if (num > 0)
                System.out.println("插入成功!!");
        } finally {
            JdbcUtils.release(conn, st, rs);
        }
    }

  @Test
    public void read() throws SQLException, IOException {
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection();
            String sql = "select id, resume from testclob where id='1'";
            st = conn.prepareStatement(sql);
            rs = st.executeQuery();

            if (rs.next()) {
                // String resume = rs.getString("resume"); 不能這樣作,內存會崩

                Reader reader = rs.getCharacterStream("resume"); //<---重點
                FileWriter writer = new FileWriter("e:\\1.txt");
                try {
                    int len = 0;
                    char buffer[] = new char[1024];
                    while ((len = reader.read(buffer)) > 0) {
                        writer.write(buffer, 0, len);
                    }
                } finally {
                    if (reader != null) {
                        reader.close();
                    }
                    if (writer != null) {
                        writer.close();
                    }
                }
            }
        } finally {
            JdbcUtils.release(conn, st, rs);
        }
    }
}

db.properties以下:

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/day15
username=root
password=root

對於MySQL中的BLOB類型,可調用以下方法設置:

PreparedStatement. setBinaryStream(i, inputStream, length);

對MySQL中的BLOB類型,可調用以下方法獲取:

InputStream in  = resultSet.getBinaryStream(i);
InputStream in  = resultSet.getBlob(i).getBinaryStream();

實驗所用的表:

create table testclob ( id varchar(40) primary key, image blob );

細節,略。

4. jdbc 實現數據庫批處理

小知識: truncate table testbatch; 清除 testbatch 中的全部數據。
下面例子展示了 oracle 的強大。插入 10000006 條記錄,mysql 用大約3小時,而 oracle 只用 380秒,即 6 分多鐘!

例子(展現了2種批處理的方式):
第二種方式適合作批量插入和更新,而第一種方式可發不一樣種的sql語句。實際開發中,第二種用的多!

package cn.itcast.demo;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import org.junit.Test;

import cn.itcast.utils.JdbcUtils;

public class Demo3 {

    /*
     create table testbatch
     (
        id varchar(40) primary key,
        name varchar(40)
     );  
    */

    //實現批處理第一種方式
    @Test
    public void test1() throws SQLException{
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;

        try{
            conn = JdbcUtils.getConnection();
            String sql1 = "insert into testbatch(id,name) values('1','aaa')";
            String sql2 = "update testbatch set name='bbb' where id='1'";

            st = conn.createStatement();  //list
            st.addBatch(sql1);
            st.addBatch(sql2);

            //[3,4]
            st.executeBatch();
            st.clearBatch();

        }finally{
            JdbcUtils.release(conn, st, rs);
        }
    }


    //實現批處理的第二種方式
    @Test
    public void test2() throws SQLException{

        long starttime = System.currentTimeMillis();
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;

        try{
            conn = JdbcUtils.getConnection();
            String sql = "insert into testbatch(id,name) values(?,?)";   //做批量插入   批量更新
            st = conn.prepareStatement(sql);

            for(int i=1;i<=10000006;i++){
                st.setString(1, i+"");
                st.setString(2, "aa" + i);
                st.addBatch();
                if(i%1000==0){
                    st.executeBatch(); // 每1000個sql作成批,向數據庫發一次
                    st.clearBatch(); // 清除 st 維護的 list 中的數據
                }
            }
            st.executeBatch(); // 剩餘的部分作成批,最後再向數據庫發一次
        }finally{
            JdbcUtils.release(conn, st, rs);
        }

        long endtime = System.currentTimeMillis();
        System.out.println("總花了:" + (endtime-starttime)/1000 + "秒");
    }
}

5. jdbc 獲取數據庫自動生成的主鍵和調用存儲過程

5.1 數據庫自動生成的主鍵

public class Demo4 {
    /**
     獲取自動生成的主鍵
     use day15;
     create table test(
        id int primary key auto_increment,
        name varchar(40)
     );
     */
    public static void main(String[] args) throws SQLException {
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection();
            String sql = "insert into test(name) values('aaa')";

            // 設置st是否能獲取自動生成的主鍵    但下面的設置不起任何做用,不知爲啥
            st = conn.prepareStatement(sql, Statement.NO_GENERATED_KEYS); //<--
            st.executeUpdate();
            rs = st.getGeneratedKeys(); // <-- 重點
            if(rs.next()){
                System.out.println(rs.getInt(1));
            }
        } finally {
            JdbcUtils.release(conn, st, rs);
        }
    }
}

5.2 jdbc 調用存儲過程(procedure) - 金融證券領域用的特多

金融證券領域的開發沒法使用 hibernate,由於數據庫表結構是保密的,只有存儲過程暴露在外。此領域只能經過 jdbc 調用存儲過程去獲取數據。

存儲過程就是數據庫那面的方法或者函數。處理數據用。如今,咱們有兩種方式從數據庫中獲取咱們想要的數據:

  1. 在數據庫中編寫存儲過程,由該 procedure 把處理後的數據給咱們;
  2. 直接把數據庫的數據拉到咱們這來,咱們經過 java 編寫函數來處理數據,最終獲取咱們想要的數據。

銀行的業務,如利息是在數據庫中用存儲過程來實現的,而不是在數據庫外用其餘語言如 java,由其餘 coder 實現!

試驗準備,編寫一個存儲過程,以下:

use day15;
delimiter $$

CREATE PROCEDURE demoSp(IN inputParam VARCHAR(255), INOUT inOutParam varchar(255))
BEGIN
    SELECT CONCAT('zyxw---', inputParam) into inOutParam;
END $$

delimiter ;

獲得CallableStatement,並調用存儲過程:

CallableStatement cStmt = conn.prepareCall("{call demoSp(?, ?)}");

設置參數,註冊返回值,獲得輸出:

cStmt.setString(1, "abcdefg");
cStmt.registerOutParameter(2, Types.VARCHAR);
cStmt.execute();
System.out.println(cStmt.getString(2));

完整例子:

public class Demo5 {
    public static void main(String[] args) throws SQLException {
        Connection conn = null;
        CallableStatement cStmt = null;
        ResultSet rs = null;        

        try {
            conn = JdbcUtils.getConnection();
            cStmt = conn.prepareCall("{call demoSp(?,?)}");

            cStmt.setString(1, "haha");
            cStmt.registerOutParameter(2, Types.VARCHAR);
            cStmt.execute();
            System.out.println(cStmt.getString(2));
        } finally {
            JdbcUtils.release(conn, cStmt, rs);
        }
    }
}

6. ResultSet 對結果集進行滾動

ResultSet 提供了對結果集進行滾動的方法:

  • next():移動到下一行
  • Previous():移動到前一行
  • absolute(int row):移動到指定行
  • beforeFirst():移動resultSet的最前面。
  • afterLast() :移動到resultSet的最後面

可對小數據量內容分頁,不可應用於大數據量,由於數據量大時,ResultSet 對象會很大。應該象第 1 節分頁實現裏講的那樣,你要那些數據,就查詢哪些數據進行顯示,而不是一次性把全部數據拿回來,封裝到 ResultSet 對象中再處理,這種方式若數據量足夠大,內存會崩!

相關文章
相關標籤/搜索