文章目录
- 前言
- 一、访问安全文件目录中资源
- 控制器
- 二、通过Navicat查看所创建的数据库
- 创建一个用户JavaBean
- 四、JDBC编程
- 1. 加载驱动
- 2. 获取连接
- 3. 创建语句
- 增加操作
- 删除操作
- 修改操作
- 4. 执行语句
- 5. 处理结果
- 查询操作
- 查询一个对象
- 查询所有用户
- 6. 回收资源
- 总结
前言
文章用于记录本次JavaWeb连接数据库上机时的各种细节,本篇主要记录服务端和数据库进行数据交流
一、访问安全文件目录中资源
当文件资源如jsp文件、html文件放置在WEB-INF目录中时,不能通过浏览器直接输入文件路径进行访问,此时需要通过使用控制器来进行访问。
在此例中,通过创建UserServlet控制器来进行访问。
控制器
控制器一般只做三件事情:
- 接请求,拿参数
- 调业务,封装数据,置作用域对象
- 做跳转,业务导航
package com.zfh.controller;
import java.io.IOException;
import java.sql.SQLException;
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.zfh.pojo.User;
import com.zfh.test.JdbcConnection;
@WebServlet("/users")
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 1. 接请求,拿参数
// 2. 调业务,封装数据,置作用域对象
List<User> users = null;
try {
users = JdbcConnection.selectUsers();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
request.setAttribute("users", users);
// 3. 做跳转,业务导航
request.getRequestDispatcher("WEB-INF/users.jsp").forward(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
此处只需要做第三件事,通过控制转发语句,访问安全目录下的users.jsp文件
二、通过Navicat查看所创建的数据库
输入对应参数后连接数据库查看本次上机时利用的数据库,目的是对照,测试代码是否有误。
创建一个用户JavaBean
此用户类名为user
其成员变量为
id(非空)、name、gender、age、score、create_time(非空)
均使用封装数据类型(其好处是可以使用多种类方法、且更为安全)
这里重写了toString()方法,目的是调用可以输出成员变量的值用来观察测试,而不是观察对象的引用。
package com.zfh.pojo;
import java.io.Serializable;
import java.util.Date;
public class User implements Serializable {
private Integer id;
private String name;
private String gender;
private Integer age;
private Double score;
private Date create_time;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Double getScore() {
return score;
}
public void setScore(Double score) {
this.score = score;
}
public Date getCreate_time() {
return create_time;
}
public void setCreate_time(Date create_time) {
this.create_time = create_time;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", gender=" + gender + ", age=" + age + ", score=" + score
+ ", create_time=" + create_time + "]";
}
public User() {}
public User(String name, String gender, Integer age, Double score) {
super();
this.name = name;
this.gender = gender;
this.age = age;
this.score = score;
}
}
四、JDBC编程
JDBC编程需要以下六个步骤
其中加载驱动和获取连接需要以下四个属性
driver、url、username、password
将其封装在JdbcConnection类中
public class JdbcConnection {
/**
* 数据库连接参数
* driver,url,username,password
*/
private static final String DRIVER = "com.mysql.jdbc.Driver";
private static final String URL = "jdbc:mysql://localhost:3306/test_db";
private static final String USERNAME = "root";
private static final String PASSWORD = "123456";
private static Connection conn = null;
private static PreparedStatement ps = null;
private static ResultSet rs = null;
}
此处将后续方法中会使用到的对象也封装为成员变量
1. 加载驱动
使用Class类下的静态方法forName来加载驱动
Class.forName(driverClass);
其中driverClass为数据库驱动类所对应的字符串
static {
try {
Class.forName(DRIVER);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
这里直接捕获异常
2. 获取连接
public static Connection getConn() throws SQLException {
Connection conn = null;
conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
return conn;
}
这里向上抛出异常,方便后续调用时灵活处理异常
3. 创建语句
创建语句的步骤为:
1.获取connection对象
2.创建sql语句
3.通过connection对象创建statement对象
一般使用prepareStatement(String sql),传入的sql语句通常带有?占位符。
其目的是方便后续进行替换?中的内容,方便修改,提高可读性。
增加操作
public static int insertUser(User user) throws SQLException {
//获取connection对象
conn = getConn();
//创建sql语句,使用了?占位符
String sql = "insert into t_user(name,gender,age,score)"
+ " values(?,?,?,?)";
//通过connection对象创建statement对象
ps = conn.prepareStatement(sql);
//将?占位符进行替换
ps.setString(1, user.getName());
ps.setString(2, user.getGender());
ps.setInt(3, user.getAge());
ps.setDouble(4, user.getScore());
return ps.executeUpdate();
}
使用问号占位符,方便后续处理
删除操作
public static int deleteUser(int id) throws SQLException {
//获取connection对象
conn = getConn();
//创建sql语句,使用了?占位符
String sql = "delete from t_user where id=?";
//通过Connection对象创建Statement对象
ps = conn.prepareStatement(sql);
//将第一个?替换为id值
ps.setInt(1, id);
//执行更新语句
return ps.executeUpdate();
}
修改操作
public static int updateUser(User user) throws SQLException {
//获取connection对象
conn = getConn();
//创建sql语句,使用了?占位符
String sql = "update t_user set name=?,gender=?,age=?,score=?"
+ " where id=?";
//通过connection对象创建statement对象
ps = conn.prepareStatement(sql);
//将?占位符进行替换
ps.setString(1, user.getName());
ps.setString(2, user.getGender());
ps.setInt(3, user.getAge());
ps.setDouble(4, user.getScore());
ps.setInt(5, user.getId());
//执行更新语句
return ps.executeUpdate();
}
4. 执行语句
使用Statement对象执行SQL语句
常用executeUpdate()和executeQuery()方法
执行DML和DDL语句
- executeUpdate()
执行DML语句返回受SQL语句影响的行数
执行DDL语句返回0 - executeQuery()
只能执行查询语句
返回代表查询结果的ResultSet对象
ResultSet对象的实质是一个查询结果集,在逻辑结构上非常类似于一个表。
5. 处理结果
查询操作
查询一个对象
/**
* 按id查询一个用户
* @throws SQLException
*/
public static User selectUser(int id) throws SQLException {
//创建一个user对象,由于不知道查询结果是否存在,因此初始化为null
User user = null;
//获取connection对象
conn = getConn();
//创建sql查询语句,查询条件包含?占位符
String sql = "select id,name,gender,age,score,create_time from t_user where id=?";
//通过connection对象创建statement对象
ps = conn.prepareStatement(sql);
//将?占位符替换为需要查询用户的id
ps.setInt(1, id);
//执行查询语句,返回结果集
rs= ps.executeQuery();
//使用迭代的方式查找,由于id是主键,
//因此返回的结果集只有1或0(不存在)
if (rs.next()) {
//查询成功,为user对象申请内存空间
user = new User();
user.setId(rs.getInt("id"));
user.setName(rs.getString("name"));
user.setGender(rs.getString("gender"));
user.setAge(rs.getInt("age"));
user.setScore(rs.getDouble("score"));
user.setCreate_time(rs.getDate("create_time"));
}
//返回user对象
return user;
}
查询所有用户
ResultSet对象如下图所示,初始时指向第一个数据行的上一行,调用next函数后向下滚动一行。如果当前指向是最后一行,调用next函数后指向了最后一行的下一行,返回null
/**
* 查询所有用户
* @throws SQLException
*/
public static List<User> selectUsers() throws SQLException {
//由于查询的结果不止一个,因此需要创建一个链表来保存数据
List<User> users = new ArrayList<>();
//获取connection对象
conn = getConn();
//创建sql语句
String sql = "select id,name,gender,age,score,create_time from t_user";
//通过connection对象创建statement对象
ps = conn.prepareStatement(sql);
//执行查询语句
rs= ps.executeQuery();
//使用迭代器进行循环保存结果集的每一行到链表中
while (rs.next()) {
//指针所指的一行有记录,创建user对象保存记录
User user = new User();
user.setId(rs.getInt("id"));
user.setName(rs.getString("name"));
user.setGender(rs.getString("gender"));
user.setAge(rs.getInt("age"));
user.setScore(rs.getDouble("score"));
user.setCreate_time(rs.getDate("create_time"));
//将封装好的数据添加到users链表中
users.add(user);
}
//返回保存了查询结果的user链表
return users;
}
6. 回收资源
调用close()方法,关闭连接。
public static void close(Connection myConn) throws SQLException {
if (myConn != null) {
myConn.close();
}
}
总结
本篇主要是服务端和数据库交流,从数据库中查询数据,然后进行相应处理和向数据库更新数据包括增上改。在下篇中会介绍在jsp页面中通过使用jstl语言让服务端和客户端进行交流。