实现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','zs@sina.com','1980-12-04');INSERT INTO users(NAME,PASSWORD,email,birthday)
-> VALUES('lisi','123456','lisi@sina.com','1981-12-04');INSERT INTO users(NAME,PASSWORD,email,birthday)
-> VALUES('wangwu','123456','wangwu@sina.com','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, "zl@sina.com");preStmt.setString(4, "1989-12-23");// 3.执行SQLpreStmt.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查找指定的userpublic 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("hl@sina.com");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("zhaoxiaoliu@sina.com");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, HttpServletResponseresponse)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();}//判断集合中是否存在所要登录的usernameif (usernameList.contains(loginName)) {//查找username对应的passwordList<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界面如下图所示: