JDBC在Java Web中的应用

制作人:全心全意

在Java Web开发中,JDBC的应用十分广泛。通常情况下,Web程序操作数据库都是通过JDBC实现,即使目前数据库方面的开源框架层出不穷,但其底层实现也离不开JDBC API。

开发模式

在Java Web开发中使用JDBC,应遵循MVC的设计思想,从而使Web程序拥有一定的健壮性、可扩展性。

MVC(Model-View-Conntroller)是一种程序设计理念,该理念将软件分成3层结构,分别为模型层、视图层和控制层。其中模型层泛指程序中的业务逻辑,用于处理真正的业务操作;视图层是指程序与用户交互的页面,对用户呈现出视图,但不包含业务逻辑;控制层是对用户各种请求的分发处理,将指定的请求分配给指定的业务逻辑进行处理。

JDBC应用于Java Web开发中,处于MVC中的模型层位置,如下图所示。

客户端通过JSP页面与程序进行交互,对于数据的增、删、改、查请求由Servlet对其进行分发处理,如Servlet接收到添加数据请求,就会分发给增加数据的JavaBean对象,而真正的数据库操作是通过JDBC封装的JavaBean进行实现。

分页查询

分页查询是Java Web开发中常用的技术。在数据库量非常大的情况下,不适合将所有数据显示到一个页面中,既给查看带来方便,又占用了程序及数据库的资源,此时就需要对数据进行分页查询。

通过JDBC实现分页查询的方法有很多种,而且不同的数据库机制也提供了不同的分页方式,下面介绍两种典型的分页方法。

  • 通过ResultSet的光标实现分页

  ResultSet是JDBC API中封装的查询结果集对象,通过该对象可以实现数据的分页显示。在ResultSet对象中,有一个“光标”的概念,光标通过上下移动定位查询结果集中的行,从而获取数据。所以通过ResultSet的移动“光标”,可以设置ResultSet对象中记录的起始位置和结束位置,来实现数据的分页显示。

  通过ResultSet的光标实现分页,优点是在各种数据库上通用,缺点是占用大量资源,不适合数据量大的情况。

  • 通过数据库机制进行分页

  很多数据库自身都提供了分页机制,如SQL Server中提供的top关键字,MySQL数据库中提供的limit关键字,它们都可以设置数据返回的记录数。

  通过各种数据库提供的分页机制实现分页查询,其优点是减少数据库资源的开销,提供程序的性能;缺点是只针对某一种数据库通用。

说明:由于通过ResultSet的光标实现数据分页存在性能方面的缺陷,所以,在实际开发中,很多情况下都是采用数据库提供的分页机制来实现分页查询功能。

示例一:通过MySQL数据库提供的分页机制,实现商品信息的分页查询功能,将分页数据显示在JSP页面中

示例一建表语句:

CREATE TABLE `tb_product` (
`id` int(11) NOT NULL,
`name` varchar(255) DEFAULT NULL,
`num` int(11) DEFAULT NULL,
`price` double DEFAULT NULL,
`unit` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

Product类:封装商品信息,该类是商品信息的JavaBean

package com.zq;

public class Product {
public static int PAGE_SIZE = 2; // 每页记录数
private int id;// 编号
private String name;// 名称
private double price;// 价格
private int num;// 数量
private String unit;// 单位 public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public double getPrice() {
return price;
} public void setPrice(double price) {
this.price = price;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getNum() {
return num;
} public void setNum(int num) {
this.num = num;
} public String getUnit() {
return unit;
} public void setUnit(String unit) {
this.unit = unit;
} }

在Product类中,主要封装了商品对象的基本信息。除此之外,Product类还定义了分页中的每页记录数。

ProductDao类:封装商品对象的数据库相关操作

package com.zq;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List; public class ProductDao {
// 获取数据库连接
public Connection getConnection() {
Connection conn = null;
try {
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8";
String username = "root";
String password = "";
conn = DriverManager.getConnection(url, username, password);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
} // 分页查询所有商品信息
public List<Product> find(int page) {
List<Product> list = new ArrayList<Product>();
Connection conn = getConnection();
String sql = "select * from tb_product order by id desc limit ?,?";
try {
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1, (page - 1) * Product.PAGE_SIZE);
ps.setInt(2, Product.PAGE_SIZE);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
Product p = new Product();
p.setId(rs.getInt("id"));
p.setName(rs.getString("name"));
p.setNum(rs.getInt("num"));
p.setPrice(rs.getDouble("price"));
p.setUnit(rs.getString("unit"));
list.add(p);
}
rs.close();
ps.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
return list;
} // 查询总记录数
public int findCount() {
int count = 0;
Connection conn = getConnection();
String sql = "select count(*) from tb_product";
try {
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql);
if (rs.next()) {
count = rs.getInt(1);
}
rs.close();
stmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
return count;
}
}

  

FindServlet类:分页查询商品信息的Servlet对象

package com.zq;

import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List; import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; @WebServlet("/FindServlet")
public class FindServlet extends HttpServlet {
private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
int currPage = 1;
if (request.getParameter("page") != null) {
currPage = Integer.parseInt(request.getParameter("page"));
}
ProductDao dao = new ProductDao();
List<Product> list = dao.find(currPage);
request.setAttribute("list", list);
int pages;
int count = dao.findCount();
if (count % Product.PAGE_SIZE == 0) {
pages = count / Product.PAGE_SIZE;
} else {
pages = count / Product.PAGE_SIZE + 1;
}
StringBuffer sb = new StringBuffer();
for (int i = 1; i < pages + 1; i++) {
if (i == currPage) {
sb.append("『" + i + "』");
} else {
sb.append("<a href='FindServlet?page=" + i + "'>" + i + "</a>");
}
sb.append(" ");
} request.setAttribute("bar", sb.toString()); System.out.println(sb.toString());
request.getRequestDispatcher("product_list.jsp").forward(request, response);
} }

FindServlet类的doGet()方法主要做了两件事,分别为获取分页查询结果集及构造分页条对象。其中获取分页查询结果非常简单,通过调用ProductDao类的find()方法,并传递所要查询的页码就可以获取;分页条对象是JSP页面中的分页条,用于显示商品信息的页码,程序中主要通过创建页码的超链接,然后组合字符串进行构造

product_list.jsp页面:通过获取查询结果集List与分页条来分页显示商品信息数据

<%@page import="com.zq.Product"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>主页</title>
</head>
<body>
<table align="center" width="450" border="1">
<tr>
<td align="center" colspan="5">
<h2>所有商品信息</h2>
</td>
</tr>
<tr align="center">
<td><b>ID</b></td>
<td><b>商品名称</b></td>
<td><b>价格</b></td>
<td><b>数量</b></td>
<td><b>单位</b></td>
</tr>
<%
List<Product> list = (List<Product>) request.getAttribute("list");
int i = 1;
if (request.getParameter("page") != null) {
i = Integer.parseInt(request.getParameter("page")) * 2 - 1;
}
for (Product p : list) {
%>
<tr>
<td><%=i++%></td>
<td><%=p.getName()%></td>
<td><%=p.getPrice()%></td>
<td><%=p.getNum()%></td>
<td><%=p.getUnit()%></td>
</tr>
<%
}
%>
<tr>
<td align="center" colspan="5"><%=request.getAttribute("bar")%>
</td>
</tr>
</table> </body>
</html>

  

index.jsp页面:程序主页面

<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>首页</title>
</head>
<body>
<a href="FindServlet">查看所有商品信息</a>
</body>
</html>

JDBC在Java Web中的应用的更多相关文章

  1. JDBC在Java Web中的应用——分页查询

    分页查询 通过JDBC实现分页查询的方法有很多种,而且不同的数据库机制也提供了不同的分页方式,在这里介绍两种非常典型的分页方法. 通过ResultSet的光标实现分页 通过ResultSet的光标实现 ...

  2. 第三章 深入分析Java Web中的中文编码问题

    3.1 几种常见的编码格式 3.1.1 为什么要编码 一个字节 byte只能表示0~255个符号,要表示更多的字符,需要编码. 3.1.2 如何翻译 ASCII码:有128个,用一个字节的低7位表示. ...

  3. 【中文乱码】深入分析 Java Web 中的中文编码问题

    深入分析 Java Web 中的中文编码问题 1.几种常见的编码格式 1.1 为什么要编码 在计算机中存储信息的最小单元是 1 个字节,即 8 个 bit, 所以能表示的字符范围是 0 ~ 255 个 ...

  4. Java Web 中 过滤器与拦截器的区别

    过滤器,是在java web中,你传入的request,response提前过滤掉一些信息,或者提前设置一些参数,然后再传入servlet或者struts的 action进行业务逻辑,比如过滤掉非法u ...

  5. JAVA WEB 中的编码分析

    JAVA WEB 中的编码分析 */--> pre.src {background-color: #292b2e; color: #b2b2b2;} pre.src {background-co ...

  6. Java web中常见编码乱码问题(一)

    最近在看Java web中中文编码问题,特此记录下. 本文将会介绍常见编码方式和Java web中遇到中文乱码问题的常见解决方法: 一.常见编码方式: 1.ASCII 码 众所周知,这是最简单的编码. ...

  7. Java web中常见编码乱码问题(二)

    根据上篇记录Java web中常见编码乱码问题(一), 接着记录乱码案例: 案例分析:   2.输出流写入内容或者输入流读取内容时乱码(内容中有中文) 原因分析: a. 如果是按字节写入或读取时乱码, ...

  8. 深入分析Java Web中的编码问题

    编码问题一直困扰着我,每次遇到乱码或者编码问题,网上一查,问题解决了,但是实际的原理并没有搞懂,每次遇到,都是什么头疼. 决定彻彻底底的一次性解决编码问题. 1.为什么要编码 计算机的基本单元是字节, ...

  9. 解决java web中safari浏览器下载后文件中文乱码问题

    解决java web中safari浏览器下载后文件中文乱码问题 String fileName = "测试文件.doc"; String userAgent = request.g ...

随机推荐

  1. js实现IOS上删除app时颤抖动画j函数

    欢迎提供更好的方法! <!--http://www.cnblogs.com/webzhangnan/p/3244920.html --> <html> <head> ...

  2. 22 WPF列表,树,网格

    ListView ListView从ListBox派生,只增加了View属性.如果你没有设置View属性,ListView行为正如ListBox. 从技术上,View属性指向任何ViewBase派生类 ...

  3. codeforces GYM 100781A【树的直径】

    先求出每棵树的直径,排个序,要想图的直径最小的话需要每棵树的直径中点像直径最大的树的直径中点连边,这样直径有三种情况:是直径最大的树的直径:a[tot]:是直径最大的树和直径第二大的树的半径拼起来+1 ...

  4. bzoj 1770: [Usaco2009 Nov]lights 燈【高斯消元+dfs】

    参考:https://blog.csdn.net/qq_34564984/article/details/53843777 可能背了假的板子-- 对于每个灯建立方程:与它相邻的灯的开关次数的异或和为1 ...

  5. 清北考前刷题day1下午好

    水题(water) Time Limit:1000ms   Memory Limit:128MB 题目描述 LYK出了道水题. 这个水题是这样的:有两副牌,每副牌都有n张. 对于第一副牌的每张牌长和宽 ...

  6. Akka源码分析-Cluster-Metrics

    一个应用软件维护的后期一定是要做监控,akka也不例外,它提供了集群模式下的度量扩展插件. 其实如果读者读过前面的系列文章的话,应该是能够自己写一个这样的监控工具的.简单来说就是创建一个actor,它 ...

  7. fprintf写入字符串入文件/fread读取文件内的字符串

    #include <stdio.h> #include <string.h> #include <stdlib.h> int main(void) { FILE * ...

  8. HTML基础2——综合案例3——创建考试报名表格

    <html> <head> <title></title> </head> <body> <table width=&qu ...

  9. List 的属性与方法整理

    List<T> 类与 ArrayList 类比较类似.它实现了 IList<T> 泛型接口,长度可以动态增加. 可以使用 Add 或 AddRange 方法将项添加到 List ...

  10. Python Turtle绘图

    1. 画布(canvas) 画布就是turtle为我们展开用于绘图区域, 我们可以设置它的大小和初始位置 1.1 设置画布大小 turtle.screensize(canvwidth=None, ca ...