考试JDBC项目速成
项目结果:

构建对应数据库类型的类
样例的学生数据库比较简单,只有学号,姓名,年龄3个属性.对应的类也需要写出3种属性(用类的原因是后面可以包装成List操作方便)
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package model;
/**
*
* @author 郑佳杰
*/
public class Student {
private String sno;
private String sname;
private int sage;
public Student(String sno, String sname, int sage) {
this.sno = sno;
this.sname = sname;
this.sage = sage;
}
public Student() {
}
public String getSno() {
return sno;
}
public void setSno(String sno) {
this.sno = sno;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public int getSage() {
return sage;
}
public void setSage(int sage) {
this.sage = sage;
}
}
访问数据库的通用读写方法类
首先要写出3个对象

分别对应ado.net连接数据库的coon,cmd,dataset。
之后写
连接函数
try {
//1、加载驱动类
Class.forName("com.mysql.jdbc.Driver");
//2、创建连接对象
String url = "jdbc:mysql://localhost:3306/my_db?useUnicode=true&characterEncoding=utf-8";
String user = "root";
String password = "123456";
conn = DriverManager.getConnection(url,user,password);
} catch (Exception e) {
e.printStackTrace();
}
return conn;
}
//装载驱动语法记住!!
Class.forName("com.mysql.jdbc.Driver");
//2、创建连接对象
//url记住!!
String url = "jdbc:mysql://localhost:3306/my_db?useUnicode=true&characterEncoding=utf-8";
String user = "root";
String password = "123456";
关闭函数
比较简单
public void closeAll(Connection conn, PreparedStatement pstmt, ResultSet rs) {
try {
if (rs != null) {
rs.close();
}
if (pstmt != null) {
pstmt.close();
}
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
增删改操作
public int executeUpdate(String sql, Object[] params) {
this.getConnection();//前提保证数据库连接
int result = 0;
try {
//3、创建prepareStatement对象
pstmt = conn.prepareStatement(sql);//和ado.net给cmd附值查询字符串一个道理
//4、为占位符赋值
if (null != params) {
for (int i = 0; i < params.length; i++) {
pstmt.setObject(i + 1, params[i]);//Object是任何对象的父类,也就是说可以转换成任何的类型
//setObject下标从1开始
}
}
//5、调用方法:执行sql语句
result = pstmt.executeUpdate();
//pstmt.executeUpdate()返回受影响行数,为int类型
} catch (SQLException e) {
e.printStackTrace();
} finally {
this.closeAll(conn, pstmt, null);
}
return result;
}
查询方法
和上面几乎一样 但是区别在于上面用的是executeUpdate(String sql); 可执行增,删,改,返回执行受到影响的行数。
该处使用的是执行SQL查询,并返回ResultSet 对象。
public ResultSet executQuery(String sql, Object[] params) {
this.getConnection();
try {
//3、创建prepareStatement对象
pstmt = conn.prepareStatement(sql);
//4、为占位符赋值
if (null != params) {
for (int i = 0; i < params.length; i++) {
pstmt.setObject(i + 1, params[i]);
}
}
//5、调用方法:执行sql语句
rs = pstmt.executeQuery();
} catch (SQLException e) {
e.printStackTrace();
}
//后面具体的查询方法还需要用到rs ,所以此处最后不能关闭数据流
return rs;
}
总体代码:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package dal;
/**
*
* @author 郑佳杰
*/
import java.sql.*;
public class Dbutils {
protected Connection conn = null;
protected PreparedStatement pstmt = null;
protected ResultSet rs = null;
/**
* 获取连接对象
* @return 连接对象
*/
public Connection getConnection() {
try {
//1、加载驱动类
Class.forName("com.mysql.jdbc.Driver");
//2、创建连接对象
String url = "jdbc:mysql://localhost:3306/my_db?useUnicode=true&characterEncoding=utf-8";
String user = "root";
String password = "123456";
conn = DriverManager.getConnection(url,user,password);
} catch (Exception e) {
e.printStackTrace();
}
return conn;
}
/**
* 关闭资源
*
* @param conn
* @param pstmt
* @param rs
*/
public void closeAll(Connection conn, PreparedStatement pstmt, ResultSet rs) {
try {
if (rs != null) {
rs.close();
}
if (pstmt != null) {
pstmt.close();
}
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 增删改操作
*
* @param sql
* @param params
* @return
*/
public int executeUpdate(String sql, Object[] params) {
this.getConnection();
int result = 0;
try {
//3、创建prepareStatement对象
pstmt = conn.prepareStatement(sql);
//4、为占位符赋值
if (null != params) {
for (int i = 0; i < params.length; i++) {
pstmt.setObject(i + 1, params[i]);
}
}
//5、调用方法:执行sql语句
result = pstmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
this.closeAll(conn, pstmt, null);
}
return result;
}
/**
* 查询方法
*
* @param sql
* @param params
* @return
*/
public ResultSet executQuery(String sql, Object[] params) {
this.getConnection();
try {
//3、创建prepareStatement对象
pstmt = conn.prepareStatement(sql);
//4、为占位符赋值
if (null != params) {
for (int i = 0; i < params.length; i++) {
pstmt.setObject(i + 1, params[i]);
}
}
//5、调用方法:执行sql语句
rs = pstmt.executeQuery();
} catch (SQLException e) {
e.printStackTrace();
}
//后面具体的查询方法还需要用到rs ,所以此处最后不能关闭数据流
return rs;
}
}
定义了对Student表进行增删改查操作的方法
查询所有人的信息
Dbutils dbutils = new Dbutils();
//返回所有的用户信息
public List<Student> findAllStudents() {
String sql = "select sno,sname,sage from student";
Object[] params = null;//params的作用就是给select语句中出现的?赋值,这里没有?故直接设置为Null
List<Student> list = new ArrayList<>();
ResultSet rs = dbutils.executQuery(sql, params);
try {
if (null != rs) {
//如果rs不为空,则循环将信息写入List中
while (rs.next()) {
Student student = new Student();
student.setSno(rs.getString("sno"));
student.setSname(rs.getString("sname"));
student.setSage(rs.getInt("sage"));
list.add(student);
}
}
} catch (SQLException ex) {
ex.printStackTrace();
} finally {
dbutils.closeAll(dbutils.conn, dbutils.pstmt, dbutils.rs);
}
return list;
}
根据学号查找信息
public Student findBySno(String sno) {
Student student = new Student();
String sql = "select sno,sname,sage from student where sno=?";
//这里select语句出现一个? 需要params去给他赋值
//故params值为函数使给的学号
Object[] params = {sno};
ResultSet rs = dbutils.executQuery(sql, params);
try {
if (null != rs) {
if (rs.next()) {
student.setSno(rs.getString("sno"));
student.setSname(rs.getString("sname"));
student.setSage(rs.getInt("sage"));
}
}
} catch (SQLException ex) {
ex.printStackTrace();
} finally {
dbutils.closeAll(dbutils.conn, dbutils.pstmt, dbutils.rs);
}
return student;
}
判断学号在student表中是否存在
//和上面函数几乎一个道理。
public boolean isSnoExist(String sno) {
boolean flag = false;
String sql = "select sno,sname,sage from student where sno=?";
Object[] params = {sno};
ResultSet rs = dbutils.executQuery(sql, params);
try {
if (rs != null && rs.next()) {
flag = true;
}
} catch (SQLException ex) {
ex.printStackTrace();
}
return flag;
}
差不多的操作
//一个道理www
public boolean insert(Student student) {
boolean flag = false;
String sql = "insert into student(sno,sname,sage) values(?,?,?)";
Object[] params = {student.getSno(), student.getSname(), student.getSage()};
return (dbutils.executeUpdate(sql, params) == 1);
//executeUpdate返回受影响的行数,如果不是1说明插入失败!
}
//根据学号,更新该生的其他属性
public boolean update(Student student) {
String sql = "update student set sname=?,sage=? WHERE sno=?";
Object[] params = {student.getSname(), student.getSage(), student.getSno()};
return dbutils.executeUpdate(sql, params) == 1;
}
//根据学号删除学生信息
public boolean deleteBySno(String sno) {
String sql = "delete from student where sno=?";
Object[] params = {sno};
return dbutils.executeUpdate(sql, params) == 1;
}
}
到此为止 数据库功能已经几乎实现,接下来需要实现servlet和jsp
学生管理页面jsp
html注释太蛋疼了 这里仍然使用//做注释
<%--
Document : student
Created on : 2021-1-12, 22:29:51
Author : 郑佳杰
--%>
<%@page import="dal.StudentDAO"%>
<%@page import="java.util.List"%>
<%@page import="model.Student"%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>学生信息管理</title>//标题设置
<script type="text/javascript">
function p_del() {
var msg = "您真的确定要删除吗?请确认!";
//jsp 的confirm函数会自动生成一个提问框 记住就好!
if (confirm(msg) == true) {
return true;
} else {
return false;
}
}
</script>
</head>
<body>
<div align="center">
<h1>学生信息管理</h1>
<%
StudentDAO studentDAO = new StudentDAO();
//通过调用函数获取所有学生信息
List<Student> students = studentDAO.findAllStudents();
%>
<table border='1' width="90%" >
//tr包的是一整行
//th定义是表头属性
<tr><th width="20%">编号</th>
<th width="20%">学生学号</th>
<th width="20%">姓名</th>
<th width="20%">年龄</th>
<th width="20%">操作</th>
</tr>
<%
int rowNum = 0;//行编号
for (int i = 0; i < students.size(); i++) {
rowNum++;
String sno = students.get(i).getSno();
String sname = students.get(i).getSname();
int sage = students.get(i).getSage();
String deleteLink = "delete?sno=" + sno;
String editLink = "editPage.jsp?sno=" + sno;
//在传达的地方后面跟?既代表传递参数
//比如我定义了一个print.jsp 里面需要一个参数name
//定义一个超链接<a href="print.jsp?name=1"</a> 那么跳到print.jsp时 会知道name的值为1
%>
//下面为html语法,不能被jsp的<% %>包住
<tr>
<td><%= rowNum%></td>
<td><%= sno%></td>
<td><%= sname%></td>
<td><%= sage%></td>
<!--点击“删除”链接,使用javascript脚本弹出确认对话框,单击“确定”后,才执行删除操作-->
//<%=%>为jsp的格式,他会将里面的变量值解析出来,如果只是单纯的a href="deleteLink" 由于是在html范围,不会知道这是一个前面定义过的变量。无法实现我们的要求
<td><a href="<%=deleteLink%>" onClick="javascript:return p_del();">删除</a>
<a href='<%=editLink%>'>修改</a></td>
</tr>
//别忘记了循环最后一个括号,必须被jsp的<% %>包住
<%
}
%>
</table>
<br/>
//添加信息 使用表单来实现 get方式,交给路径为/add的文件(servlet)处理
<form action="add" method = "get">
学号 <input name="sno">
姓名 <input name="sname">
年龄 <input name="sage">
<input type="submit" value="增加"></br>
</form>
</div>
</body>
</html>
管理学生信息jsp
其中,通过调用dal.studentDAO类的findBySno(Sring sno)方法,返回被选中的学生的基本信息。
<%@page import="model.Student"%>
<%@page import="dal.StudentDAO"%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSP Page</title>
</head>
<body>
<h1>编辑学生信息</h1>
<%
StudentDAO studentDAO = new StudentDAO();
String sno = request.getParameter("sno");
//获得对应的sno值,对应前面来自主界面跳转到此页面时传递了一个?sno=xx
Student student = studentDAO.findBySno(sno);
//通过该函数来获取学生的其他信息
String sname = student.getSname();
int sage = student.getSage();
%>
<form action="edit" method = "get">
//交给路径为./edit(servlet)的文件处理,也是get方式
<!--通过readonly="true",设置学号文本框不能修改-->
学号 <input name="sno" readonly="true" value=<%=sno%>><br/>
姓名 <input name="sname" value=<%=sname%>><br/>
年龄 <input name="sage" value=<%=sage%>><br/><br/>
<input type="submit" value="提交"></br>
</form>
</body>
</html>
此时jsp部分已经完全O了 ,剩下jsp实现添加 更新 删除时是交给servlet文件处理的,因此还需要实现3个servlet
实现添加功能Servlet
package servlet;
import dal.StudentDAO;
import java.io.IOException;
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import model.Student;
@WebServlet("/add")//路径一定要和前面jsp的对应,前面Jsp添加是交给add路径文件处理
public class AddServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置请求对象的编码方案为utf-8
req.setCharacterEncoding("utf-8");
//设置响应对象以及浏览器的字符方案为utf-8
resp.setContentType("text/html;charset=utf-8");
//这里记不住就随便新建一个jsp,会看到系统初始化jsp用了同样的字符串!!!
StudentDAO studentDAO = new StudentDAO();
//获取用户输入的学号,判断学号在学生表中是否存在
String sno = req.getParameter("sno");
if (studentDAO.isSnoExist(sno)) {
resp.getWriter().println("<script>alert('学号重复,添加失败');window.location.href='student.jsp'</script>");
//出现学号重复,alert为弹出信息框,跳转到之前的页面
//window.location.href='' 是单引号! 使当前网页跳到指定地方 既跳回去
} else {
//获取用户输入的姓名、年龄
String sname = req.getParameter("sname");
String sageStr = req.getParameter("sage");
Integer sage = Integer.parseInt(sageStr);
Student student = new Student(sno, sname, sage);
studentDAO.insert(student);
//使用javascript脚本输出提示对话框,并跳转到student.jsp页面中
resp.getWriter().println("<script>alert('添加成功');window.location.href='student.jsp'</script>");
//上面看懂了 这应该看得懂
}
//不能使用resp.sendRedirect("student.jsp");否则,javascript对话框无法显示。
}
}
实现删除功能Servl
package servlet;
import dal.StudentDAO;
import java.io.IOException;
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
@WebServlet("/delete")//记住路径一样
public class DeleteServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
StudentDAO studentDAO = new StudentDAO();
String sno = req.getParameter("sno");
//这里跳到删除功能是从表格上已有信息的地方跳到,所以必定保证删除的学号存在,不需要加各种判断
//根据用户输入的学号,删除学生记录
studentDAO.deleteBySno(sno);
//重定向到首页student.jsp
//按老师的说法就是 需要出现一个对话框加跳转页面需要用到<script></script>语法
//这里没有对话框要弹 就随便了
resp.sendRedirect("student.jsp");
}
}
实现更新servlet
package servlet;
import dal.StudentDAO;
import java.io.IOException;
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import model.Student;
@WebServlet("/edit")
public class EditServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
StudentDAO studentDAO = new StudentDAO();
//获取数值
String sno = req.getParameter("sno");
String sname = req.getParameter("sname");
String sageStr = req.getParameter("sage");
int sage = Integer.parseInt(sageStr);
//转成int类型
Student student = new Student(sno, sname, sage);
if (studentDAO.update(student)) {
resp.getWriter().println("<script>alert('修改成功');window.location.href='student.jsp'</script>");
} else {
//真到考场 这边想不起来就不加判断了 前面jsp的编辑页面保证学号不能改,那么基本是不会出现错误的
resp.getWriter().println("<script>alert('程序发生了未知的错误,修改失败');window.location.href='student.jsp'</script>");
}
}
}
到此为止 我们实现了目标!
总结
做这种东西一定要理清楚思路,先定义什么类,要实现什么功能。
操作尽量包装成函数,同时变量定义要规范!

浙公网安备 33010602011771号