考试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>");
        }
    }
}

到此为止 我们实现了目标!

总结

做这种东西一定要理清楚思路,先定义什么类,要实现什么功能。
操作尽量包装成函数,同时变量定义要规范!

posted @ 2021-01-12 23:00  一个经常掉线的人  阅读(210)  评论(0)    收藏  举报