何须浅碧轻红色,自是花中第一流。 —李清照的《鹧鸪天·桂花》
- JDBC 简介
- 我实验的MySQL数据库
- 配置连接MySQL驱动
- 数据库连接工具类
- JDBC API
- Driver 接口
- Connection 接口
- DriverManager 类
- Statement 接口
- PreparedStatement 接口
- CallableStatement 接口
- ResultSet 接口
- JDBC 数据库操作
- 测试连接示例
- 添加数据
- 查询信息
- 修改数据
- 删除数据
- 批处理
- 调用存储过程
JDBC 简介
JDBC 全称为 Java Data Base Connectivity
,是 Java 程序与数据库系统通信的标准 API,它定义在 JDK 的 API 中。
JDBC 就像一座 Java 运用和数据库连接的桥梁。
1 我实验的MySQL数据库
数据库名:db_book
表名:tb_book
建表语句
DROP TABLE IF EXISTS `tb_book`;
CREATE TABLE `tb_book` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT NULL,
`price` float DEFAULT NULL,
`bookCount` int(11) DEFAULT NULL,
`author` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2 配置连接MySQL驱动
MySQL驱动 mysql-connector-java-5.1.39 下载http://download.csdn.net/detail/peng_hong_fu/9645521
在 Project 新建 lib目录,然后如图
3 数据库连接工具类
DBUtil.java
//package com.peng.db;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DBUtil {
private static final String URL = "jdbc:mysql://127.0.0.1:3306/db_book?characterEncoding=utf8&useSSL=false";
private static final String USER = "root";
private static final String PASSWORD = "root";
private static Connection conn = null;
static {// 加载类时会执行这些静态的代码块
try {
// 1.加载驱动程序
Class.forName("com.mysql.jdbc.Driver");
// 2.获得数据库连接
conn = DriverManager.getConnection(URL, USER, PASSWORD);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
public static Connection getConn() {
return conn;
}
}
JDBC API
1 Driver 接口
每种数据库的驱动程序都应该提供一个实现java.sql.Driver
接口的类,简称 Driver 类,在加载 Driver 类时,应该创建自己的实例并向 java.sql.DriverManager
类注册该实例。
// 1.加载驱动程序
Class.forName("com.mysql.jdbc.Driver");
2 Connection 接口
Connection 接口位于java.sql
包中,负责与特定数据库的连接。在数据库应用开发时,只有获得了特定数据库的连接对象,才能访问数据库,操作数据库中的数据表、视图和存储过程等。
void close() 立即释放此 Connection 对象的数据库和 JDBC 资源,而不是等待它们被自动释放。
void commit() 使所有上一次提交/回滚后进行的更改成为持久更改,并释放此 Connection 对象当前持有的所有数据库锁。
Statement createStatement() 创建一个 Statement 对象来将 SQL 语句发送到数据库。
boolean getAutoCommit()获取此 Connection 对象的当前自动提交模式。
void setAutoCommit(boolean autoCommit) 将此连接的自动提交模式设置为给定状态。默认为true 自动提交
void rollback() 取消在当前事务中进行的所有更改,并释放此 Connection 对象当前持有的所有数据库锁。
PreparedStatement prepareStatement(String sql) 创建一个 PreparedStatement 对象来将参数化的 SQL 语句发送到数据库。
.
.
更多方法http://www.apihome.cn/api/java/Connection.html
3 DriverManager 类
DriverManager 类主要作用于用户及驱动程序之间,它是 JDBC 中的管理层,通过 DriverManager 类可以管理数据库厂商提供的驱动程序,并建立应用程序与数据库之间的连接。
static void deregisterDriver(Driver driver) 从 DriverManager 的列表中删除一个驱动程序。
static Connection getConnection(String url) 试图建立到给定数据库 URL 的连接。
static Connection getConnection(String url, Properties info)试图建立到给定数据库 URL 的连接。
static Connection getConnection(String url, String user, String password)试图建立到给定数据库 URL 的连接。
static Driver getDriver(String url) 试图查找能理解给定 URL 的驱动程序。
.
.
更多方法:http://www.apihome.cn/api/java/DriverManager.html
4 Statement 接口
在创建数据库连接之后,就可以通过程序来调用 SQL 语句来对数据库进行操作了,在 JDBC 中 Statement 接口封装了这些操作。Statement 接口提供了执行语句和获取查询结果的基本方法。
boolean execute(String sql) 执行指定的 SQL 语句。如果SQL语句返回执行结果,返回true
ResultSet executeQuery(String sql) 执行查询类型(SELECT)的 SQL 语句。此方法返回查询获得的结果集 ResultSet 对象
Connection getConnection() 获取生成此 Statement 对象的 Connection 对象
.
.
更多方法http://tool.oschina.net/apidocs/apidoc?api=jdk_7u4
5 PreparedStatement 接口
PreparedStatement 接口继承于 Statement,它拥有 Statement 接口中的方法,而且针对带参数 SQL 语句的执行操作进行了扩展,解决了SQL语句需要将程序中的变量作为查询条件的参数的问题,而且更加安全,可以使用占位符 ? 来代替 SQL 语句中的参数,然后在对其进行赋值。
Java 提供了高效的数据库操作机制,那就是 PreparedStatement 对象,该对象被习惯地称作预处理语句对象。
向数据库发送一个 SQL 语句时,如 " select * from goods"
,数据库中的SQL 解释器负责把SQL 语句生成底层的内部命令,然后执行该命令,完成有关的数据操作。如果不断向数据库 SQL 语句势必增加数据库中 SQL 解释器的负担,影响执行的速度。如果应用程序能针对连接的数据库,事先就将 SQL语句解释为数据库底层的命令,然后直接让数据库执行这个命令,显然不仅减轻了数据库的负担,而且也提高了访问数据库的速度。
对于 JDBC ,如果使用 Connection 和某个数据库建立了连接对象 conn , 那么 con 就可以调用
PreparedStatement prepareStatement(String sql)
throws SQLException
方法对参数 sql 指定的 SQL 语句进行预编译处理,生成该数据库底层的命令,并将该命令封装在 PreparedStatement 对象中,那么该对象调用下列方法都可以使得该底层内部命令被数据库执行。
boolean execute(String sql) 执行指定的 SQL 语句。如果SQL语句返回执行结果,返回true
ResultSet executeQuery(String sql) 执行查询类型(SELECT)的 SQL 语句。此方法返回查询获得的结果集 ResultSet 对象
Connection getConnection() 获取生成此 Statement 对象的 Connection 对象
void setDate(int parameterIndex, Date x) 使用运行应用程序的虚拟机的默认时区将指定参数设置为给定 java.sql.Date 值。
void setDouble(int parameterIndex, double x) 将指定参数设置为给定 Java double 值。
void setFloat(int parameterIndex, float x) 将指定参数设置为给定 Java REAL 值。
void setInt(int parameterIndex, int x) 将指定参数设置为给定 Java int 值。
void setLong(int parameterIndex, long x) 将指定参数设置为给定 Java long 值。
void setTimestamp(int parameterIndex, Timestamp x) 将指定参数设置为给定 java.sql.Timestamp 值。
.
.
6 CallableStatement 接口
CallableStatement 继承于 PreparedStatement 接口,是 PreparedStatement 接口的扩展,用来执行 SQL 的存储过程。
若数据库有存储过程select_count()
BEGIN
SELECT count(*) INTO counts FROM tb_book;
END
/**
* 带输出参数的存储过程
*
* @return
* @throws SQLException
*/
public static Integer select_count() throws SQLException {
Integer count;
// 获取连接
Connection conn = DBUtil.getConn();
// 获取CallableStatement
CallableStatement cs = conn.prepareCall("call select_count(?)");
cs.registerOutParameter(1, Types.INTEGER);
cs.execute();
count = cs.getInt(1);
return count;
}
7 ResultSet 接口
执行 SQL 语句的查询语句会返回查询的结果集, 在 JDBC API 中,使用 ResultSet 对象接收查询结果集。
ResultSet 对象包含了符合 SQL 语句的所有行,针对 Java 的数据类型提供了一套 getter 方法,通过这些方法可获取每一行的数据,ResultSet 还提供了光标的功能,通过光标可以自由定位到某一行的数据。
byte getByte(int columnIndex) 以 Java 编程语言中 byte 的形式获取此 ResultSet 对象的当前行中指定列的值。
Reader getCharacterStream(int columnIndex) 以 java.io.Reader 对象的形式获取此 ResultSet 对象的当前行中指定列的值。
Date getDate(int columnIndex) 以 Java 编程语言中 java.sql.Date 对象的形式获取此 ResultSet 对象的当前行中指定列的值。
double getDouble(int columnIndex) 以 Java 编程语言中 double 的形式获取此 ResultSet 对象的当前行中指定列的值。
float getFloat(int columnIndex) 以 Java 编程语言中 float 的形式获取此 ResultSet 对象的当前行中指定列的值。
int getInt(int columnIndex) 以 Java 编程语言中 int 的形式获取此 ResultSet 对象的当前行中指定列的值。
long getLong(int columnIndex) 以 Java 编程语言中 long 的形式获取此 ResultSet 对象的当前行中指定列的值。
String getString(int columnIndex) 以 Java 编程语言中 String 的形式获取此 ResultSet 对象的当前行中指定列的值。
Time getTime(int columnIndex) 以 Java 编程语言中 java.sql.Time 对象的形式获取此 ResultSet 对象的当前行中指定列的值。
Timestamp getTimestamp(int columnIndex) 以 Java 编程语言中 java.sql.Timestamp 对象的形式获取此 ResultSet 对象的当前行中指定列的值。
boolean next() 将光标从当前位置向前移一行。如果新行有效则返回true
更多方法:http://www.apihome.cn/api/java/ResultSet.html
JDBC 数据库操作
1 测试连接示例
使用预处理命令处理 MySQL 数据库查询命令
数据库名:db_book
user: root
password:root
表名 :tb_book
JavaBean 类
Book.java
//package com.jdbc.model;
/**
* Title: Book
* Description: Book实体类
* @author Peng
* @date 上午9:53:46
*/
public class Book {
private int id;// 编号
private String name;// 图书名称
private double price;// 定价
private int bookCount;// 数量
private String author;// 作者
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public int getBookCount() {
return bookCount;
}
public void setBookCount(int bookCount) {
this.bookCount = bookCount;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
@Override
public String toString() {
return "Book [id=" + id + ", name=" + name + ", price=" + price + ", bookCount=" + bookCount + ", author="
+ author + "]";
}
}
TestConn.java
//package com.jdbc.test;
public class TestConn {
public static void main(String args[]) {
PrepareQuery query=new PrepareQuery();
query.setTablename("db_book");
query.setUser("root");
query.setPassword("root");
query.setSql("select name,price,author from tb_book");
query.inputQuery();
}
}
PrepareQuery.java
//package com.jdbc.test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class PrepareQuery {
// private static final String URL =
// "jdbc:mysql://127.0.0.1:3306/peng?characterEncoding=utf8&useSSL=false";
// private static final String USER = "root";
// private static final String PASSWORD = "root";
private static Connection conn = null;
private String tablename;
private String sql;
private String user;
private String password;
public void setSql(String sql) {
this.sql = sql;
}
public void setTablename(String tablename) {
this.tablename = tablename;
}
public void setUser(String user) {
this.user = user;
}
public void setPassword(String password) {
this.password = password;
}
public void inputQuery() {
try {
// 1.加载驱动程序
Class.forName("com.mysql.jdbc.Driver");
// 2.获得数据库连接
String URL = "jdbc:mysql://127.0.0.1:3306/" + tablename + "?characterEncoding=utf8&useSSL=false";
conn = DriverManager.getConnection(URL, user, password);
PreparedStatement ptmt = conn.prepareStatement(sql);
ResultSet rs = ptmt.executeQuery();
while (rs.next()) {
System.out.println(rs.getString("name") + "," + rs.getDouble("price")+rs.getString("author"));
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
JSP开发指南,45.0刘德华
SQL Server,56.0张学友
HTML+CSS,36.0黎明
2 添加数据
Insert [INTO] table_name [(column_list)] values (data_values)
这里有两个 jsp 页面,一个供用户输入图书信息,另一个接收图书信息,并执行添加数据操作,实际开发过程中,jsp页面是不负责任何逻辑业务的,这种和数据库交互业务是在 servlet 中处理的,这里只是测试。
封装数据库连接
DBUtil.java
//package com.jdbc.db;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DBUtil {
private static final String URL = "jdbc:mysql://127.0.0.1:3306/db_book?characterEncoding=utf8&useSSL=false";
private static final String USER = "root";
private static final String PASSWORD = "root";
private static Connection conn = null;
static {// 加载类时会执行这些静态的代码块
try {
// 1.加载驱动程序
Class.forName("com.mysql.jdbc.Driver");
// 2.获得数据库连接
conn = DriverManager.getConnection(URL, USER, PASSWORD);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
public static Connection getConn() {
return conn;
}
}
indexAdd.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="java.sql.*"%>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>添加图书信息</title>
<script type="text/javascript">
function check(form) {
if (form.name.value == "") {
alert("图书名称不能为空");
return false;
}
if (form.price.value == "") {
alert("定价不能为空");
return false;
}
if (form.author.value == "") {
alert("作者不能为空");
return false;
}
return true;
}
</script>
<style type="text/css">
ul {
list-style: none; /*设置不显示项目符号*/
margin: 0px; /*设置外边距*/
padding: 5px; /*设置内边距*/
}
li {
padding: 5px; /*设置内边距*/
}
</style>
</head>
<body>
<form action="addBook.jsp" method="post" onsubmit=" return check(this)">
<ul>
<li>图书名称:<input type="text" name="name" /></li>
<li>价 格:<input type="text" name="price" /></li>
<li>数 量:<input type="text" name="bookCount" /></li>
<li>作 者:<input type="text" name="author" /></li>
<li><input type="submit" value="添 加"></li>
</ul>
</form>
</body>
</html>
addBook.jsp
<%@page import="com.jdbc.db.DBUtil"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="java.sql.*" %>
<%request.setCharacterEncoding("UTF-8"); %>
<jsp:useBean id="book" class="com.jdbc.model.Book"></jsp:useBean>
<jsp:setProperty property="*" name="book"/>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>保存图书信息</title>
</head>
<body>
<%
try {
Connection conn= DBUtil.getConn();
String sql = "insert into tb_book(name,price,bookCount,author) values(?,?,?,?)"; // 添加图书信息的SQL语句
PreparedStatement ps = conn.prepareStatement(sql); // 获取PreparedStatement
ps.setString(1, book.getName()); // 对SQL语句中的第1个参数赋值
ps.setDouble(2, book.getPrice()); // 对SQL语句中的第2个参数赋值
ps.setInt(3, book.getBookCount()); // 对SQL语句中的第3个参数赋值
ps.setString(4, book.getAuthor()); // 对SQL语句中的第4个参数赋值
int row = ps.executeUpdate(); // 执行更新操作,返回所影响的行数
if (row > 0) { // 判断是否更新成功
out.print("成功添加了 " + row + "条数据!"); // 更新成输出信息
}
ps.close(); // 关闭PreparedStatement,释放资源
conn.close(); // 关闭Connection,释放资源
} catch (Exception e) {
out.print("图书信息添加失败!");
e.printStackTrace();
}
%>
<br>
<a href="index.jsp">返回</a>
</body>
</html>
3 查询信息
SELECT [ALL|DISTINCT] <目标列表表达式>[,<目标列表表达式>]...
FORM <表名或视图名>[,<表名或视图名>]
[WHERE <条件表达式>]
[GROUP BY<列名> [HAVING <条件表达式>]]
[ORDER BY <列名2>[ASC| DESC]]
如:
嵌入算术表达式
SELECT name,2016-age FROM Student
去掉重复行(默认为 ALL)
SELECT DISTINCT age FROM Student
选择
SELECT name,age FROM Student WHERE age<20
确定范围
SELECT name,age FROM Student WHERE age BETWEEN 20 AND 23
SELECT name,age FROM Student WHERE age NOT BETWEEN 20 AND 23
确定集合
SELECT name,age FROM Student WHERE age NOT IN(19,20,23)
字符匹配 "%"任意长度 "_"任意当个字符
SELECT * FROM Student WHERE name LIKE ‘刘%‘
SELECT * FROM Student WHERE name LIKE ‘刘_‘
SELECT * FROM Student WHERE name LIKE ‘_刘%‘
SELECT * FROM Student WHERE name MOT LIKE ‘刘%‘
去除通配符的影响"\" 匹配DB_Design字符
SELECT * FROM Student WHERE name ‘DB\_Design‘ ESCAPE‘\‘
涉及空值的查询
SELECT * FROM Student WHERE score IS NOT NULL
多重查询
SELECT * FROM Student WHERE Sdept="信工系" AND age<20
排序ORDER BY ASC升序 DESC降序
SELECT * FROM Student ORDER BY mumber,age DESC 按mumber降序排列,相同按年龄降序排列
聚集函数(只能用于SELECT子句和 group by 中的 having 子句)
COUNT(*) 统计元组个数
COUNT([DISTINCT|ALL] <列名>) 统计一列中值的个数
SUM([DISTINCT|ALL]<列名>) 计算一列值的总和(必须此列为数组型)
AVG([DISTINCT|ALL]<列名>) 计算一列值的平均值(必须此列为数组型)
MAX([DISTINCT|ALL]<列名>) 求一列值的最大值
MIN([DISTINCT|ALL]<列名>)
SELECT SUM(Score) FROM Student WHERE id=2010
GROUP BY子句
SELECT Cno,COUNT(Cno) FROM Student GROUP BY Cno 查询结果按Cno分组,计算每组人数
SELECT id FROM Student GROUP BY Sno HAVING COUNT(*)>3 选修了三门以上课程(Sno)的学号(id)
index.jsp 页面请求 FindServlet 在 servlet 里执行 SQL 语句,请求数据库数据,获取 Book对象的 list 集合,再携带数据跳转到 bookList.jsp ,通过request 获取数据,利用嵌入的java 的 for 循环,在页面上输出。
因为与数据库连接时 一个工具 JavaBean 类,getconn方法是一个 static 方法,所以不能再servlet 里关闭 conn 连接。
这里的连接数据库业务,执行 SQL 语句的任务,其实应该放到 dao 层
indexCha.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="java.sql.*"%>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>首页</title>
</head>
<body>
<a href="FindServlet">查看图书列表</a>
</body>
</html>
FindServlet.java
//package com.jdbc.servlet;
import java.io.IOException;
import java.sql.Connection;
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;
import com.jdbc.db.DBUtil;
import com.jdbc.model.Book;
/**
* Title: FindServlet
* Description: Servlet实现类FindServlet
* @author Peng
* @date 上午11:11:40
*/
@WebServlet("/FindServlet") // 配置Servlet
public class FindServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public FindServlet() {
super();
}
/**
* 执行POST请求的方法
*/
protected void doPostt(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
/**
* 执行GET请求的方法
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
// 创建Connection连接
Connection conn = DBUtil.getConn();
Statement stmt = conn.createStatement(); // 获取Statement
String sql = "select * from tb_book"; // 添加图书信息的SQL语句
ResultSet rs = stmt.executeQuery(sql); // 执行查询
List<Book> list = new ArrayList<>(); // 实例化List对象
while (rs.next()) { // 光标向后移动,并判断是否有效
Book book = new Book(); // 实例化Book对象
book.setId(rs.getInt("id")); // 对id属性赋值
book.setName(rs.getString("name")); // 对name属性赋值
book.setPrice(rs.getDouble("price")); // 对price属性赋值
book.setBookCount(rs.getInt("bookCount")); // 对bookCount属性赋值
book.setAuthor(rs.getString("author")); // 对author属性赋值
list.add(book); // 将图书对象添加到集合中
}
request.setAttribute("list", list); // 将图书集合放置到request中
rs.close(); // 关闭ResultSet
stmt.close(); // 关闭Statement
//conn.close();这里不能关闭
} catch (SQLException e) {
e.printStackTrace();
}
// 请求转发到bookList.jsp
request.getRequestDispatcher("bookList.jsp").forward(request, response);
}
}
bookList.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="java.util.*"%>
<%@ page import="com.jdbc.model.Book"%>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>显示图书列表</title>
<style type="text/css">
td,th {
padding: 5px;
background-color: #FFFFFF;
}
div{
width: 98%;
text-align: center;
}
table{
width:98%;
background-color: #666666;
}
tr{
text-align: center;
}
</style>
</head>
<body>
<div>
<h2>所有图书信息</h2>
</div>
<table cellspacing="1">
<tr>
<th>ID</th>
<th>图书名称</th>
<th>价格</th>
<th>数量</th>
<th>作者</th>
</tr>
<%
// 获取图书信息集合
List<Book> list = (List<Book>) request.getAttribute("list");
// 判断集合是否有效
if (list == null || list.size() < 1) {
out.print("<tr><td bgcolor=‘#FFFFFF‘ colspan=‘5‘>没有任何图书信息!</td></tr>");
} else {
// 遍历图书集合中的数据
for (Book book : list) {
%>
<tr >
<td><%=book.getId()%></td>
<td><%=book.getName()%></td>
<td><%=book.getPrice()%></td>
<td><%=book.getBookCount()%></td>
<td><%=book.getAuthor()%></td>
</tr>
<%
}
}
%>
</table>
</body>
</html>
3 修改数据
UPDATE table_name
SET <column_name>=<expression>
[...,<last column_name>=<last expression>]
[WHERE <search_condition>]
更新了 bookList.jsp ,添加一个 UpdateServlet,进行更新处理后跳转到 FindServlet 实现数据的刷新显示
bookList.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="java.util.*"%>
<%@ page import="com.jdbc.model.Book"%>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>显示图书列表</title>
<style type="text/css">
tr {
height:30px;
}
</style>
<script type="text/javascript">
function check(form){
if(form.bookCount.value == ""){
alert("请输入更新数量!");
form.bookCount.focus();
return false;
}
if(isNaN(form.bookCount.value)){
alert("格式错误!");
form.bookCount.focus();
return false;
}
return true;;
}
</script>
<style type="text/css">
td,th {
padding: 5px;
background-color: #FFFFFF;
}
div{
width: 98%;
text-align: center;
}
table{
width:98%;
background-color: #666666;
}
tr{
text-align: center;
}
</style>
</head>
<body>
<div>
<h2>所有图书信息</h2>
</div>
<table cellspacing="1">
<tr>
<th>ID</th>
<th>图书名称</th>
<th>价格</th>
<th>数量</th>
<th>作者</th>
<th>修改数量</th>
</tr>
<%
// 获取图书信息集合
List<Book> list = (List<Book>) request.getAttribute("list");
// 判断集合是否有效
if (list == null || list.size() < 1) {
out.print("<tr><td colspan=‘5‘>没有任何图书信息!</td></tr>");
} else {
// 遍历图书集合中的数据
for (Book book : list) {
%>
<tr >
<td><%=book.getId()%></td>
<td><%=book.getName()%></td>
<td><%=book.getPrice()%></td>
<td><%=book.getBookCount()%></td>
<td><%=book.getAuthor()%></td>
<td>
<!-- 在表单中加上onsubmit="return false;"可以阻止表单提交。 -->
<form action="UpdateServlet" method="post" onsubmit="return check(this);">
<input type="hidden" name="id" value="<%=book.getId()%>">
<input type="text" name="bookCount" size="3">
<input type="submit" value="修 改">
</form>
</td>
</tr>
<%
}
}
%>
</table>
</body>
</html>
UpdateServlet.java
//package com.jdbc.servlet;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.jdbc.db.DBUtil;
/**
* Title: UpdateServlet
* Description: Servlet实现类UpdateServlet
* @author Peng
* @date 下午3:55:35
*/
@WebServlet("/UpdateServlet") //配置Servlet
public class UpdateServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public UpdateServlet() {
super();
}
/**
* 处理POST请求
*/
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
int id = Integer.valueOf(request.getParameter("id"));
int bookCount = Integer.valueOf(request.getParameter("bookCount"));
try {
// 创建Connection连接
Connection conn = DBUtil.getConn();
String sql = "update tb_book set bookcount=? where id=?";// 更新SQL语句
PreparedStatement ps = conn.prepareStatement(sql);// 获取PreparedStatement
ps.setInt(1, bookCount); // 对SQL语句中的第一个参数赋值
ps.setInt(2, id); // 对SQL语句中的第二个参数赋值
ps.executeUpdate(); // 执行更新操作
ps.close(); // 关闭PreparedStatement
//conn.close();不能关闭Connection
} catch (Exception e) {
e.printStackTrace();
}
response.sendRedirect("FindServlet"); // 重定向到FindServlet
}
}
4 删除数据
DELETE FROM <table_name>[WHERE <search condition>]
增加了修改一栏 和 DeteServlet
bookList.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="java.util.*"%>
<%@ page import="com.jdbc.model.Book"%>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>显示图书列表</title>
<style type="text/css">
tr {
height:30px;
}
</style>
<script type="text/javascript">
function check(form){
if(form.bookCount.value == ""){
alert("请输入更新数量!");
form.bookCount.focus();
return false;
}
if(isNaN(form.bookCount.value)){
alert("格式错误!");
form.bookCount.focus();
return false;
}
return true;;
}
function deleteone(form){
var r=confirm("确认删除id为"+form.id.value+"的数据吗?");
return r;
}
</script>
<style type="text/css">
td,th {
padding: 5px;
background-color: #FFFFFF;
}
div{
width: 98%;
text-align: center;
}
table{
width:98%;
background-color: #666666;
}
tr{
text-align: center;
}
</style>
</head>
<body>
<div>
<h2>所有图书信息</h2>
</div>
<table cellspacing="1">
<tr>
<th>ID</th>
<th>图书名称</th>
<th>价格</th>
<th>数量</th>
<th>作者</th>
<th>修改数量</th>
<th>删除</th>
</tr>
<%
// 获取图书信息集合
List<Book> list = (List<Book>) request.getAttribute("list");
// 判断集合是否有效
if (list == null || list.size() < 1) {
out.print("<tr><td colspan=‘5‘>没有任何图书信息!</td></tr>");
} else {
// 遍历图书集合中的数据
for (Book book : list) {
%>
<tr >
<td><%=book.getId()%></td>
<td><%=book.getName()%></td>
<td><%=book.getPrice()%></td>
<td><%=book.getBookCount()%></td>
<td><%=book.getAuthor()%></td>
<td>
<!-- 在表单中加上onsubmit="return false;"可以阻止表单提交。 -->
<form action="UpdateServlet" method="post" onsubmit="return check(this);">
<input type="hidden" name="id" value="<%=book.getId()%>">
<input type="text" name="bookCount" size="3">
<input type="submit" value="修 改">
</form>
</td>
<td>
<form action="DeleteServlet" method="post" onsubmit="return deleteone(this);" >
<input type="hidden" name="id" value="<%=book.getId()%>">
<input type="submit" value="删 除">
</form>
</td>
</tr>
<%
}
}
%>
</table>
</body>
</html>
DeleteServlet.java
//package com.jdbc.servlet;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.jdbc.db.DBUtil;
/**
* Title: DeleteServlet
* Description: 删除一行的数据
* @author Peng
* @date 下午4:29:57
*/
@WebServlet("/DeleteServlet") //配置Servlet
public class DeleteServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public DeleteServlet() {
super();
}
/**
* 处理POST请求
*/
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
int id = Integer.valueOf(request.getParameter("id"));
try {
// 创建Connection连接
Connection conn = DBUtil.getConn();
String sql = "DELETE FROM tb_book where id=?";// 更新SQL语句
PreparedStatement ps = conn.prepareStatement(sql);// 获取PreparedStatement
ps.setInt(1, id); // 对SQL语句中的第一个参数赋值
ps.executeUpdate(); // 执行更新操作
ps.close(); // 关闭PreparedStatement
//conn.close();不能关闭Connection
} catch (Exception e) {
e.printStackTrace();
}
response.sendRedirect("FindServlet"); // 重定向到FindServlet
}
}
5 批处理
新建一个 db_student 数据库来测试
主要是这两句,每次的sql语句,存起来,一起提交而已
ps.addBatch()
ps.executeBatch()
这里的Batch.java 居然不用遵守JavaBean类的规范,可以通过动作标识来引用
DROP TABLE IF EXISTS `tb_student`;
CREATE TABLE `tb_student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) DEFAULT NULL,
`sex` tinyint(4) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;
Batch.java
//package com.mingrisoft;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Random;
public class Batch {
/**
* 获取数据库连接
*
* @return Connection对象
*/
public Connection getConnection() {
Connection conn = null; // 数据库连接
try {
Class.forName("com.mysql.jdbc.Driver"); // 加载数据库驱动,注册到驱动管理器
// 数据库连接字符串
String url = "jdbc:mysql://localhost:3306/db_student";
String username = "root"; // 数据库用户名
String password = "root"; // 数据库密码
// 创建Connection连接
conn = DriverManager.getConnection(url, username, password);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return conn; // 返回数据库连接
}
/**
* 批量添加数据
*
* @return 所影响的行数
*/
public int saveBatch() {
int row = 0; // 行数
Connection conn = getConnection(); // 获取数据库连接
try {
// 插入数据的SQL语句
String sql = "insert into tb_student(name,sex,age) values(?,?,?)";
// 创建PreparedStatement
PreparedStatement ps = conn.prepareStatement(sql);
Random random = new Random(); // 实例化Random
for (int i = 0; i < 10; i++) { // 循环添加数据
ps.setString(1, "学生" + i); // 对SQL语句中的第1个参数赋值
// 对SQL语句中的第2个参数赋值
ps.setBoolean(2, i % 2 == 0 ? true : false);
ps.setInt(3, random.nextInt(5) + 10); // 对SQL语句中的第3个参数赋值
ps.addBatch(); // 添加批处理命令
}
int[] rows = ps.executeBatch(); // 执行批处理操作并返回计数组成的数组
row = rows.length; // 对行数赋值
ps.close(); // 关闭PreparedStatement
conn.close(); // 关闭Connection
} catch (Exception e) {
e.printStackTrace();
}
return row; // 返回添加的行数
}
}
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<jsp:useBean id="batch" class="com.mingrisoft.Batch"></jsp:useBean>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>首页</title>
</head>
<body>
<%
// 执行批量插入操作
int row = batch.saveBatch();
out.print("批量插入了【" + row + "】条数据!");
%>
</body>
</html>
6 调用存储过程
如何创建存储过程看这里:http://blog.csdn.net/peng_hong_fu/article/details/52737402
存储过程findAllBook()
新建一个servlet FindServlet2,让 indexCha.jsp 调用FindServlet2 而不是FindServlet。
存储过程就是存放在数据库上的 SQL 语句,调用的时候,数据库查询返回结果。
CallableStatement cs = conn.prepareCall("call findAllBook()");
引入sql包
import java.sql.CallableStatement;
BEGIN
SELECT * FROM tb_book ORDER BY id DESC;
END
调用输入参数的存储过程,输出参数的存储过程,看我的这篇:http://blog.csdn.net/peng_hong_fu/article/details/52742846#t12
FindServlet2.java
//package com.jdbc.servlet;
import java.io.IOException;
import java.sql.CallableStatement;
import java.sql.Connection;
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;
import com.jdbc.db.DBUtil;
import com.jdbc.model.Book;
/**
* Title: FindServlet
* Description: Servlet实现类FindServlet2
* @author Peng
* @date 上午11:11:40
*/
@WebServlet("/FindServlet2") // 配置Servlet
public class FindServlet2 extends HttpServlet {
private static final long serialVersionUID = 1L;
public FindServlet2() {
super();
}
/**
* 执行POST请求的方法
*/
protected void doPostt(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
/**
* 执行GET请求的方法
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
// 创建Connection连接
Connection conn = DBUtil.getConn();
CallableStatement cs = conn.prepareCall("call findAllBook()");
ResultSet rs = cs.executeQuery(); // 执行查询
List<Book> list = new ArrayList<>(); // 实例化List对象
while (rs.next()) { // 光标向后移动,并判断是否有效
Book book = new Book(); // 实例化Book对象
book.setId(rs.getInt("id")); // 对id属性赋值
book.setName(rs.getString("name")); // 对name属性赋值
book.setPrice(rs.getDouble("price")); // 对price属性赋值
book.setBookCount(rs.getInt("bookCount")); // 对bookCount属性赋值
book.setAuthor(rs.getString("author")); // 对author属性赋值
list.add(book); // 将图书对象添加到集合中
}
request.setAttribute("list", list); // 将图书集合放置到request中
rs.close(); // 关闭ResultSet
cs.close(); // 关闭CallableStatement
//conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
// 请求转发到bookList.jsp
request.getRequestDispatcher("bookList.jsp").forward(request, response);
}
}