实现JDBC程序
1. 搭建数据库环境
在MySQL 中创建一个名称为jdbc的数据库,然后在该数据库中创建一个users表。创建jdbc数据库和 users 表的 SQL 语句如下:
CREATE DATABASE jdbc;
USE jdbc;
CREATE TABLE users(
-> id INT PRIMARY KEY AUTO_INCREMENT,
-> name VARCHAR(40),
-> password VARCHAR(40),
-> email VARCHAR(60),
-> birthday DATE
-> )CHARACTER SET utf8 COLLATE utf8_general_ci;
jdbc 数据库和users 表创建成功后,向users表中插入3条数据。插入数据的SQL语句如下:
INSERT INTO users(NAME,PASSWORD,email,birthday)
-> VALUES('zs','123456','[email protected]','1980-12-04');INSERT INTO users(NAME,PASSWORD,email,birthday)
-> VALUES('lisi','123456','[email protected]','1981-12-04');INSERT INTO users(NAME,PASSWORD,email,birthday)
-> VALUES('wangwu','123456','[email protected]','1979-12-04');
为了查看数据是否添加成功,可以在MySQL客户 端中使用SELECT语句查询数据表users中的数据,查询结果:
2. 创建项目环境,导入数据库驱动
在IDEA中创建一个名称为chapter10的Web项目, 将下载好的 MySQL 数据库驱动包 mysql-connector- java-8.0.15.jar 复制到项目的 lib 目录中。
将MySQL的数据库驱动添加到项目的lib目录下,在IDEA菜单栏单击【File】→【Project Structure】→ 【libraries】,进入“Project Structure”窗口:
单击【+】→【Java】,进入“Select Library Files”窗口,选择项目中lib目录下的MySQL 的数据库驱动JAR包,将MySQL的数据库驱动发布到项目的类路径下。
先单击“Apply”按钮,再单击“OK”按钮完成数据库驱动的导入。至此,MySQL的数 据库驱动就成功发布到项目的类路径下了。
3. 编写JDBC程序
在项目chapter10 的src 目录下,创建一个名称为cn.itcast.jdbc.example 的包,在该包中创建类Example01, 该类用于读取数据库中的users表,并将读取到的数据输出到控制台。
Example01.java
package cn.itcast.jdbc.example; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.sql.Date; public class Example01 { public static void main(String[] args) throws SQLException { Statement stmt = null; ResultSet rs = null; Connection conn = null; try { // 1. 注册数据库的驱动 Class.forName("com.mysql.cj.jdbc.Driver"); // 2.通过DriverManager获取数据库连接 String url = "jdbc:mysql://localhost:3306/jdbc?serverTimezone=GMT%2B8"; String username = "root";//数据库名称 String password = "root";//数据库密码 conn = DriverManager.getConnection (url, username, password); // 3.通过Connection对象获取Statement对象 stmt = conn.createStatement(); // 4.使用Statement执行SQL语句。 String sql = "select * from users"; rs = stmt.executeQuery(sql); // 5. 操作ResultSet结果集 System.out.println("id | name | password | email | birthday"); while (rs.next()) { int id = rs.getInt("id"); // 通过列名获取指定字段的值 String name = rs.getString("name"); String psw = rs.getString("password"); String email = rs.getString("email"); Date birthday = rs.getDate("birthday"); System.out.println(id + " | " + name + " | " + psw + " | " + email + " | " + birthday); } } catch (ClassNotFoundException e) { e.printStackTrace(); } finally{ // 6.回收数据库资源 if(rs!=null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } rs = null; } if(stmt!=null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } stmt = null; } if(conn!=null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } conn = null; } } } }
执行程序,控制台的打印结果截图如下:
4.PreparedStatement对象
Example02.java
package cn.itcast.jdbc.example; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement ; import java.sql.SQLException; public class Example02 { public static void main(String[] args) throws SQLException { Connection conn = null; PreparedStatement preStmt = null; try { // 加载数据库驱动 Class.forName("com.mysql.cj.jdbc.Driver"); String url = "jdbc:mysql://localhost:3306/jdbc?serverTimezone=GMT%2B8"; String username = "root"; String password = "root"; // 创建应用程序与数据库连接的Connection对象 conn = DriverManager.getConnection(url, username, password); // 执行的SQL语句 String sql = "INSERT INTO users(name,password,email,birthday)" + "VALUES(?,?,?,?)"; // 1.创建执行SQL语句的PreparedStatement对象 preStmt = conn.prepareStatement(sql); // 2.为SQL语句中的参数赋值 preStmt.setString(1, "zl"); preStmt.setString(2, "123456"); preStmt.setString(3, "[email protected]"); preStmt.setString(4, "1989-12-23"); // 3.执行SQL preStmt.executeUpdate(); } catch (ClassNotFoundException e) { e.printStackTrace(); } finally { // 释放资源 if (preStmt != null) { try { preStmt.close(); } catch (SQLException e) { e.printStackTrace(); } preStmt = null; } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } conn = null; } } } }
在MySQL 客户端中使用SELECT 语句查看users表,查询结果截图如下:
5.ResultSet对象
Example03.java
package cn.itcast.jdbc.example; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class Example03 { public static void main(String[] args) { Connection conn = null; Statement stmt = null; try { Class.forName("com.mysql.cj.jdbc.Driver"); String url = "jdbc:mysql://localhost:3306/jdbc?serverTimezone=GMT%2B8"; String username = "root"; String password = "root"; //1.获取Connection对象 conn = DriverManager.getConnection(url, username, password); String sql = "select * from users"; //2.创建Statement对象并设置常量 stmt =conn.createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); //3.执行SQL并将获取的数据信息存放在ResultSet中 ResultSet rs = stmt.executeQuery(sql); //4.取出ResultSet中指定数据的信息 System.out.print("第2条数据的name值为:"); rs.absolute(2); //将指针定位到结果集中第2行数据 System.out.println(rs.getString("name")); System.out.print("第1条数据的name值为:"); rs.beforeFirst(); //将指针定位到结果集中第1行数据之前 rs.next(); //将指针向后滚动 System.out.println(rs.getString("name")); System.out.print("第4条数据的name值为:"); rs.afterLast(); //将指针定位到结果集中最后一条数据之后 rs.previous(); //将指针向前滚动 System.out.println(rs.getString("name")); } catch (Exception e) { e.printStackTrace(); } finally { // 释放资源 if (stmt != null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } stmt = null; } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } conn = null; } } } }
运行代码,结果如下:
6.动手实践:使用JDBC完成数据的增删改查
1. 创建JavaBean
在chapter10项目的src目录下,创建包cn.itcast.jdbc.example.domain,并在该包下创建一个用户信息的实 体类User类。
User.java
package cn.itcast.jdbc.example.domain; import java.util.Date; public class User { private int id; private String username; private String password; private String email; private Date birthday; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } }
2. 创建工具类
由于每次操作数据库时都需要加载数据库驱动、建立数据库连接和关闭数据库连接,为了避免重复书写 代码,下面建立一个专门用于操作数据库的工具类。
在src目录下创建一个包cn.itcast.jdbc.example.utils,在包中创建一个封装了上述操作的工具类JDBCUtils。
JDBCUtils.java
package cn.itcast.jdbc.example.utils; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class JDBCUtils { // 加载驱动,并建立数据库连接 public static Connection getConnection() throws SQLException, ClassNotFoundException { Class.forName("com.mysql.cj.jdbc.Driver"); String url = "jdbc:mysql://localhost:3306/jdbc?serverTimezone=GMT%2B8"; String username = "root"; String password = "root"; Connection conn = DriverManager.getConnection(url, username, password); return conn; } // 关闭数据库连接,释放资源 public static void release(Statement stmt, Connection conn) { if (stmt != null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } stmt = null; } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } conn = null; } } public static void release(ResultSet rs, Statement stmt, Connection conn){ if (rs != null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } rs = null; } release(stmt, conn); } }
3. 创建DAO
在src目录下创建一个名称为cn.itcast.jdbc.example.dao的包,在包中创建一个名称为UsersDao的类。 UsersDao类主要用于程序与数据库的交互,在该类中封装了对数据库表users的添加、查询、删除和更新等 操作。
UsersDao.java
package cn.itcast.jdbc.example.dao; import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; import java.text.SimpleDateFormat; import java.util.ArrayList; import cn.itcast.jdbc.example.domain.User; import cn.itcast.jdbc.example.utils.JDBCUtils; public class UsersDao { // 添加用户的操作 public boolean insert(User user) { Connection conn = null; Statement stmt = null; ResultSet rs = null; try { // 获得数据的连接 conn = JDBCUtils.getConnection(); // 获得Statement对象 stmt = conn.createStatement(); // 发送SQL语句 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); String birthday = sdf.format(user.getBirthday()); String sql = "INSERT INTO users(id,name,password,email,birthday) "+ "VALUES(" + user.getId() + ",'" + user.getUsername() + "','" + user.getPassword() + "','" + user.getEmail() + "','" + birthday + "')"; int num = stmt.executeUpdate(sql); if (num > 0) { return true; } return false; } catch (Exception e) { e.printStackTrace(); } finally { JDBCUtils.release(rs, stmt, conn); } return false; } // 查询所有的User对象 public ArrayList<User> findAll() { Connection conn = null; Statement stmt = null; ResultSet rs = null; ArrayList<User> list = new ArrayList<User>(); try { // 获得数据的连接 conn = JDBCUtils.getConnection(); // 获得Statement对象 stmt = conn.createStatement(); // 发送SQL语句 String sql = "SELECT * FROM users"; rs = stmt.executeQuery(sql); // 处理结果集 while (rs.next()) { User user = new User(); user.setId(rs.getInt("id")); user.setUsername(rs.getString("name")); user.setPassword(rs.getString("password")); user.setEmail(rs.getString("email")); user.setBirthday(rs.getDate("birthday")); list.add(user); } return list; } catch (Exception e) { e.printStackTrace(); } finally { JDBCUtils.release(rs, stmt, conn); } return null; } // 根据id查找指定的user public User find(int id) { Connection conn = null; Statement stmt = null; ResultSet rs = null; try { // 获得数据的连接 conn = JDBCUtils.getConnection(); // 获得Statement对象 stmt = conn.createStatement(); // 发送SQL语句 String sql = "SELECT * FROM users WHERE id=" + id; rs = stmt.executeQuery(sql); // 处理结果集 while (rs.next()) { User user = new User(); user.setId(rs.getInt("id")); user.setUsername(rs.getString("name")); user.setPassword(rs.getString("password")); user.setEmail(rs.getString("email")); user.setBirthday(rs.getDate("birthday")); return user; } return null; } catch (Exception e) { e.printStackTrace(); } finally { JDBCUtils.release(rs, stmt, conn); } return null; } // 删除用户 public boolean delete(int id) { Connection conn = null; Statement stmt = null; ResultSet rs = null; try { // 获得数据的连接 conn = JDBCUtils.getConnection(); // 获得Statement对象 stmt = conn.createStatement(); // 发送SQL语句 String sql = "DELETE FROM users WHERE id=" + id; int num = stmt.executeUpdate(sql); if (num > 0) { return true; } return false; } catch (Exception e) { e.printStackTrace(); } finally { JDBCUtils.release(rs, stmt, conn); } return false; } // 修改用户 public boolean update(User user) { Connection conn = null; Statement stmt = null; ResultSet rs = null; try { // 获得数据的连接 conn = JDBCUtils.getConnection(); // 获得Statement对象 stmt = conn.createStatement(); // 发送SQL语句 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); String birthday = sdf.format(user.getBirthday()); String sql = "UPDATE users set name='" + user.getUsername() + "',password='" + user.getPassword() + "',email='" + user.getEmail() + "',birthday='" + birthday + "' WHERE id=" + user.getId(); int num = stmt.executeUpdate(sql); if (num > 0) { return true; } return false; } catch (Exception e) { e.printStackTrace(); } finally { JDBCUtils.release(rs, stmt, conn); } return false; } }
4.创建测试类
(1)在cn.itcast.jdbc.example包中创建测试类JdbcInsertTest,实现向users表中添加数据的操作。
JdbcInsertTest.java
package cn.itcast.jdbc.example; import java.util.Date; import cn.itcast.jdbc.example.dao.UsersDao; import cn.itcast.jdbc.example.domain.User; public class JdbcInsertTest{ public static void main(String[] args) { // 向users表插入一个用户信息 UsersDao ud = new UsersDao(); User user = new User(); user.setId(5); user.setUsername("hl"); user.setPassword("123"); user.setEmail("[email protected]"); user.setBirthday(new Date()); boolean b=ud.insert(user); System.out.println(b); } }
运行代码,在MySQL 客户端中使用SELECT 语句查询users 表,查询结果截图如下:
(2)在cn.itcast.jdbc.example包中创建测试类 FindAllUsersTest,实现读取users表中所有的数据。
FindAllUsersTest.java
package cn.itcast.jdbc.example; import java.util.ArrayList; import cn.itcast.jdbc.example.dao.UsersDao; import cn.itcast.jdbc.example.domain.User; public class FindAllUsersTest{ public static void main(String[] args) { //创建一个名称为usersDao的对象 UsersDao usersDao = new UsersDao(); //将UsersDao对象的findAll()方法执行后的结果放入list集合 ArrayList<User> list = usersDao.findAll(); //循环输出集合中的数据 for (int i = 0; i < list.size(); i++) { System.out.println("第" + (i + 1) + "条数据的username值为:" + list.get(i).getUsername()); } } }
在cn.itcast.jdbc.example 包中创建测试类FindAllUsersTest,运行,控制台会打印出users表中所有的username 值,结果截图如下:
(3)在cn.itcast.jdbc.example包中编写测试类FindUserByIdTest,实现读取users表中指定的数据。
FindUserByIdTest.java
package cn.itcast.jdbc.example; import cn.itcast.jdbc.example.dao.UsersDao; import cn.itcast.jdbc.example.domain.User; public class FindUserByIdTest{ public static void main(String[] args) { UsersDao usersDao = new UsersDao(); User user = usersDao.find(1); System.out.println("id为1的User对象的name值为:"+user.getUsername()); } }
在cn.itcast.jdbc.example 包中编写测试类FindUserByIdTest,运行,程序执行后,结果截图如下:
(4)在cn.itcast.jdbc.example包中创建测试类UpdateUserTest,实现修改users表中数据的操作。
UpdateUserTest.java
package cn.itcast.jdbc.example; import java.util.Date; import cn.itcast.jdbc.example.dao.UsersDao; import cn.itcast.jdbc.example.domain.User; public class UpdateUserTest{ public static void main(String[] args) { // 修改User对象的数据 UsersDao usersDao = new UsersDao(); User user = new User(); user.setId(4); user.setUsername("zhaoxiaoliu"); user.setPassword("456"); user.setEmail("[email protected]"); user.setBirthday(new Date()); boolean b = usersDao.update(user); System.out.println(b); } }
在cn.itcast.jdbc.example 包中创建测试类UpdateUserTest,使用SELECT语句查看users 表,查询结果截图如下:
(5)在cn.itcast.jdbc.example 包中创建测试类 DeleteUserTest,DeleteUserTest 类实现了删除 users 表中数据 的操作。
DeleteUserTest.java
package cn.itcast.jdbc.example; import cn.itcast.jdbc.example.dao.UsersDao; public class DeleteUserTest{ public static void main(String[] args) { // 删除操作 UsersDao usersDao = new UsersDao(); boolean b = usersDao.delete(4); System.out.println(b); } }
在cn.itcast.jdbc.example 包中创建测试类DeleteUserTest,在MySQL 客户端中使用SELECT语句查询users 表中的数据,结果截图如下:
任务:网站用户登录功能
大型网站只有在用户登录成功后才能进行相关操作,本任务要求实现一个用户登录功能。用户登录时, 需要在数据库中判断是否存在该用户的信息并验证用户信息的正确性。
【实现步骤】
本任务使用所学的JDBC知识实现用户的登录功能,具体编程思路如下:
(1)获取登录页面的username和password。
(2)遍历数据库中tb_user数据表,是否存在username,存在则继续执行程序,不存在则结束程序。
(3)遍历数据库中tb_user数据表,查找对应username的password,判断password是否与登录页面的 password一致,一致则完成登录,不一致则跳出。
1. 创建数据库表
本任务使用创建的名称为jdbc的数据库,然后在该数据库中创建一个tb_user表,并在tb_user 表中插入一条用户数据,SQL语句如下:
use JDBC;
create table tb_user (
-> id int not null primary key auto_increment,-- id主键
-> username varchar(40) not null,-- 账户名称,设置不为空
-> password varchar(40) not null,-- 密码,设置不为空
-> name varchar(40) default null,-- 用户真实姓名,默认为空
-> gender varchar(20) default null,-- 用户性别,默认为空
-> phonenumber varchar(30) default null,-- 用户手机号码,默认为空
-> identitycode varchar(30) default null-- 用户身份证号码,默认为空
-> );insert into tb_user VALUES
-> (1,'张三','123','张三','male','13888888888','110202107075023');
2. 编写登录页面
在web目录下创建一个名称为login的JSP文件,在该文件中添加用户登录时输入用户信息的表单元素。
login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>登录页面</title> </head> <style> * { margin: 0; padding: 0; } form { display: block; height: auto; width: 450px; margin: 100px auto; } form table tr { height: 40px; } form table tr td { height: 40px; width: 280px; line-height: 40px; } form table tr td input { height: 32px; border: 1px solid #BABABA; border-radius: 6px; } .alignRight { text-align: right; line-height: 40px; font-size: 16px; font-family: "Monaco"; width: 200px; } .submit { display: block; height: 40px; width: 250px; color: white; font-weight: bold; font-size: 18px; background-color: #98ECAC; border-radius: 8px; margin: 15px auto; } </style> <body> <form action="LoginServlet" method="post"> <table> <tr> <td class="alignRight"> Username: </td> <td> <input type="text" name="username" /> </td> </tr> <tr> <td class="alignRight"> Password: </td> <td> <input type="password" name="password" /> </td> </tr> </table> <input type="submit" value="登 录" class="submit" /> </form> </body> </html>
第6~48行代码定义了用户登录表单元素的CSS样式;第50~70行代码定义了一个 form表单,表单中包含了用户登录时所要填写的用户名、密码和登录按钮等元素。
3. 编写工具类
由于每次操作数据库时,都需要加载数据库驱动、建立数据库连接和关闭数据库连接,为了避免重复书 写代码,下面建立一个专门用于操作数据库的工具类。
在src目录的cn.itcast包下创建一个GetConnection工具类,具体代码如下所示:
package cn.itcast; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class GetConnection { Connection conn = null; public Connection getConnection() throws ClassNotFoundException { String driver="com.mysql.cj.jdbc.Driver"; //驱动路径 String url= "jdbc:mysql://localhost:3306/jdbc?serverTimezone=" + "GMT%2B8&useUnicode=true&characterEncoding=utf-8"; //数据库地址 String user="root"; //访问数据库的用户名 String password="root"; //用户密码 Class.forName(driver); try { conn = DriverManager.getConnection(url,user,password); } catch (SQLException e) { e.printStackTrace(); } //返回Connection对象 return conn; } }
第8~12行代码定义了数据库连接的驱动路径、数据库地址、数据库用户名和密码等 属性;第13行代码用于加载驱动类;第15行代码用于获取数据库连接;第20行代码用于返回数据库连接 对象。
4. 实现登录功能的LoginServlet
在项目src目录下的cn.itcast包下创建LoginServlet类,用于封装用户的登录信息并对用户信息进行校验。 LoginServlet类的实现如下所示。
package cn.itcast; 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 java.io.IOException; import java.io.PrintWriter; import java.sql.*; import java.util.ArrayList; import java.util.List; @WebServlet(name = "LoginServlet",urlPatterns = "/LoginServlet") public class LoginServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException { //设置请求编码、响应方式和编码方式 request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); response.setContentType("text/html"); PrintWriter out = response.getWriter(); Connection conn = null; Statement st = null; ResultSet rs = null; PreparedStatement ptst = null; //获取登录页面提交的数据 String loginName = request.getParameter("username"); String loginPassword = request.getParameter("password"); //sql语句 String selectUsername = "select username from tb_user"; String selectPassword = "select password from tb_user where username = ?"; try { //获取与数据库的链接 conn = new GetConnection().getConnection(); //遍历tb_user表,将数据库中所有username存入集合中 st = conn.createStatement(); rs = st.executeQuery(selectUsername); List<String> usernameList = new ArrayList<String>(); while (rs.next()) { usernameList.add(rs.getString(1)); } //关闭连接 if (rs != null) { rs.close(); } if (st != null) { st.close(); } //判断集合中是否存在所要登录的username if (usernameList.contains(loginName)) { //查找username对应的password List<String> passwordList = new ArrayList<String>(); ptst = (PreparedStatement) conn.prepareStatement(selectPassword); //设置ptst参数 ptst.setString(1, loginName); rs = ptst.executeQuery(); while (rs.next()) { passwordList.add(rs.getString(1)); } //判断数据库与登录页面提交的password是否一致 if (passwordList.get(0).equals(loginPassword)) { out.println("欢迎登录。"); } else { out.println("密码错误,请重新输入。"); } if (rs != null) { rs.close(); } if (ptst != null) { ptst.close(); } } else { out.println("用户名不存在"); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { //关闭链接 if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } out.flush(); out.close(); } }
第17~19行代码设置请求编码、响应方式和编码方式。第26行和第27行代码获 取用户输入的用户名、密码等属性的值。第29行和第30行代码用于从数据库中查询是否有该用户信息。 第35~40行代码遍历tb_user表,将数据库中所有username存入集合中。第42~47行代码关闭连接。第 49~71行代码判断集合中是否含有登录的用户名,如果有,则判断密码是否正确,如果密码正确,则提 示“欢迎登录”;如果密码错误,则提示“密码错误,请重新输入”。第72~74行代码判断用户名是否存 在,如果不存在,则提示“用户名不存在”。
5. 运行项目,查看效果
在IDEA中启动Tomcat服务器,然后在浏览器中访问地址http://localhost:8080/chapter10/login.jsp,用户登 录界面和登录成功的Servlet界面如下图所示: