JSP的数据库连接
原创
©著作权归作者所有:来自51CTO博客作者叮的原创作品,请联系作者获取转载授权,否则将追究法律责任
文章目录
- (1). Connection产生操作数据库的对象
- (2). Statmement操作数据库
- (3). PreparedStatmement操作数据库
- (4). ResultSet
- 2. JDBC的DriverManager
- 3. 各种数据库驱动
- (1). Oracle
- (2). MySQL
- (3). SQLserver
- 1. 主要功能
- 2. 具体通过以下类/接口实现
- 3. JDBC访问数据库的具体步骤
- (1). 导入驱动,加载具体的驱动类
- (2). 与数据库建立连接
- (3). 发送SQL,执行语句(增删改、查询)
- (4). 处理结果集(查询)
- (5). 关闭连接
- (6). 举例理解jdbc增删改查
- (7). 举例理解通过PreparedStatement操作数据库
- 1. PreparedStatement与Statement在使用时的区别
- 2. 推荐使用PreparedStatement
- 1. 模板总结
- 2. CallableStatement
- 3. 处理CLOB[Text]/BLOB类型
一. JDBC概述
JDBC:Java DataBase Connectivity
可以为多种关系型数据库DBMS提供统一的访问方式,目的就是使用Java来操作数据库
1. JDBC的API
提供了各种操作、访问接口,
类或接口的名字有:
- Connection
- Statmement
- PreparedStatement
- ResultSet
(1). Connection产生操作数据库的对象
Connection产生Statement对象:createStatement()
Connection产生PreparedStatement对象:prepareStatement()
Connection产生CallableStatement对象:prepareCall()
(2). Statmement操作数据库
增删改:executeUpdate()
查询:executeQuery()
(3). PreparedStatmement操作数据库
public interface PreparedStatement extends Statement
因此具有Statmement的方法
增删改:executeUpdate()
查询:executeQuery()
而且比Statmement还具有赋值操作
(4). ResultSet
保存结果集 select * from xxx
next():光标下移,判断是否有下一条数据:true/false
previous():光标上移,判断是否有下一条数据:true/false
getXxx(字段名|位置):获取具体的字段值
2. JDBC的DriverManager
管理不同的数据库驱动
3. 各种数据库驱动
相应的数据库厂商提供的(第三方提供)
连接、直接操作数据库
使用jdbc操作数据库时,如果对数据库进行了更换,只需要替换:驱动、具体驱动类、连接字符串、用户名、密码
(1). Oracle
驱动jar包
具体驱动类
连接字符串
jdbc:oracle:thin:@localhost:1521:ORCL
(2). MySQL
驱动jar包
mysql-connector-java-x.jar
具体驱动类
连接字符串
jdbc:mysql://localhost:3306/数据库实例名
(3). SQLserver
驱动jar包
具体驱动类
com.microsoft.sqlserver.jdbc.SQLServerDriver
连接字符串
jdbc:microsoft:sqlserver:localhost:1433;databaseename=数据库实例名
二. JDBC API
1. 主要功能
2. 具体通过以下类/接口实现
- DriverManager:管理JDBC驱动
- Connection:连接数据库(通过DriverManager产生)
- Statement (子类:PreparedStatement):增删改查(通过Connection产生)
- CallableStatement:调用数据库中的存储过程/存储函数(通过Connection产生)
- Result:返回的结果集(上面的Statement等产生)
从上之下,依次产生
3. JDBC访问数据库的具体步骤
(1). 导入驱动,加载具体的驱动类
导入驱动
加载具体的驱动类
(2). 与数据库建立连接
通过DriverManager来建立连接
Connection con = DriverManager.getConnection(URL, username, password);
返回值就是与数据库的连接对象
(3). 发送SQL,执行语句(增删改、查询)
执行增删改查需要通过:Statement (或子类:PreparedStatement)
Statement stmt = con.createStatement();
执行增删改语句:
String sql1 = "insert into tb_admins values('张三', '123')";
int count = stmt.executeUpdate(sql);//返回值表示增删改几条数据
执行查询语句:
String sql2 = "select fd_username, fd_password from userdb";
(4). 处理结果集(查询)
处理增删改的结果集
if(count>0) {
System.out.println("操作成功!");
}
处理查询的结果集
(5). 关闭连接
stmt.close();
con.close();
(6). 举例理解jdbc增删改查
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class JDBCDemo {
private final static String URL = "jdbc:mysql://localhost:3306/userdb?serverTimezone=GMT%2B8";
private final static String username = "root";
private final static String password = "root";
public static void update() throws ClassNotFoundException, SQLException { //增删改
// 1. 导入驱动,加载具体的驱动类
Class.forName("com.mysql.cj.jdbc.Driver"); //加载具体的驱动类
// 2. 与数据库建立连接(通过DriverManager)
Connection con = DriverManager.getConnection(URL, username, password);
// 3. 发送sql,执行命令(增删改)
Statement stmt = con.createStatement();
String sql1 = "insert into tb_admins values('王五', '1234')";
// String sql1 = "update tb_admins set fd_password='12345' where fd_username='王五'"
// String sql2 = "select fd_username, fd_password from userdb";
// 4. 执行SQL语句
int count = stmt.executeUpdate(sql1); //返回值表示增删改几条数据
// 5. 处理结果
if(count>0) {
System.out.println("操作成功!");
}
// 6. 关闭连接
stmt.close();//对象.方法
con.close();
}
public static void query() throws ClassNotFoundException, SQLException {//查询
// 1. 导入驱动,加载具体的驱动类
Class.forName("com.mysql.cj.jdbc.Driver"); //加载具体的驱动类
// 2. 与数据库建立连接(通过DriverManager)
Connection con = DriverManager.getConnection(URL, username, password);
// 3. 发送sql,执行命令(查询)
Statement stmt = con.createStatement();
String sql2 = "select fd_username, fd_password from tb_admins";
// 4. 执行SQL语句
ResultSet rs = stmt.executeQuery(sql2); //返回值表示查询的结果集
// 5. 处理结果
while(rs.next())
{
int pwd = rs.getInt("fd_password");
String name = rs.getString("fd_username");
// int pwd = rs.getInt(2); 这样的方式也可以,但是不推荐,要对应类型,下标:并且从1开始
// String name = rs.getString(1);
System.out.println(name+"--"+pwd);
}
// 6. 关闭连接
//先开的后关,后开的先关
rs.close();
stmt.close();//对象.方法
con.close();
}
public static void main(String[] args) throws ClassNotFoundException, SQLException {
// update();
query();
}
}
(7). 举例理解通过PreparedStatement操作数据库
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class JDBCPreparedStatementDemo {
private final static String URL = "jdbc:mysql://localhost:3306/userdb?serverTimezone=GMT%2B8";
private final static String username = "root";
private final static String password = "root";
public static void update(){ //增删改
Connection con = null;
PreparedStatement pstmt = null;
try {
// 1. 导入驱动,加载具体的驱动类
Class.forName("com.mysql.cj.jdbc.Driver"); //加载具体的驱动类
// 2. 与数据库建立连接(通过DriverManager)
con = DriverManager.getConnection(URL, username, password);
// 3. 发送sql,执行命令(增删改)
/*
stmt = con.createStatement();
// String sql1 = "update tb_admins set fd_password='12345' where fd_username='王五'"
// String sql2 = "select fd_username, fd_password from userdb";
// 4. 执行SQL语句
int count = stmt.executeUpdate(sql1); //返回值表示增删改几条数据
*/
//prepareStatement
// String sql = "insert into tb_admins values('阿飞', '12345')";
String sql = "insert into tb_admins values(?, ?)";//通过?来充当占位符
pstmt = con.prepareStatement(sql);//预编译
pstmt.setString(1, "老林");//对占位符进行替换
pstmt.setInt(2, 6666);
int count = pstmt.executeUpdate();
// 5. 处理结果
if(count>0) {
System.out.println("操作成功!");
}
}
catch(Exception e)
{
e.printStackTrace();
}
finally {
try {
// 6. 关闭连接
if(pstmt!=null)
pstmt.close();
if(con!=null)
con.close();
}catch(SQLException e) {
e.printStackTrace();
}
}
}
public static void query(){//查询
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
// 1. 导入驱动,加载具体的驱动类
Class.forName("com.mysql.cj.jdbc.Driver"); //加载具体的驱动类
// 2. 与数据库建立连接(通过DriverManager)
con = DriverManager.getConnection(URL, username, password);
// 3. 发送sql,执行命令(查询)
// String sql2 = "select fd_username, fd_password from tb_admins";
String sql2 = "select * from tb_admins where fd_username=?";
pstmt = con.prepareStatement(sql2);
pstmt.setString(1, "张三");
// 4. 执行SQL语句
rs = pstmt.executeQuery(); //返回值表示查询的结果集
// 5. 处理结果
while(rs.next())
{
int pwd = rs.getInt("fd_password");
String name = rs.getString("fd_username");
// int pwd = rs.getInt(2); 这样的方式也可以,但是不推荐,要对应类型,下标:并且从1开始
// String name = rs.getString(1);
System.out.println(name+"--"+pwd);
}
}
catch(Exception e)
{
e.printStackTrace();
}
finally {
try {
// 6. 关闭连接
if(rs!=null)
rs.close();
if(pstmt!=null)
pstmt.close();
if(con!=null)
con.close();
}catch(SQLException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws ClassNotFoundException, SQLException {
// update();
query();
}
}
1. PreparedStatement与Statement在使用时的区别
- Statement
sql
executeUpdate(sql) - PreparedStatement
sql(可能存在占位符?)
在创建PreparedStatement对象时,将sql预编译prepareStatement(sql)
执行executeUpdate()
setXxx()替换占位符?
2. 推荐使用PreparedStatement
原因如下:
- 编码更加简便,避免了字符串的拼接
String name=“zs”;
int age = 23;
stmt方式:
String sql = "insert into student(stuno,stuname) values(' "+name+" ', "+age+")";
stmt.executeUpdate(sql);
pstmt方式:
String sql = "insert into student(stuno,stuname) values(?, ?)";
pstmt = connection.prepareStatement(sql); //预编译sql
pstmt.setString(1,name);
pstmt.setString(2,age);
- 提高性能(因为有预编译操作,预编译只需要执行一次)
需要重复增减100次(批处理)
String name=“zs”;
int age = 23;
stmt方式:
String sql = "insert into student(stuno,stuname) values(' "+name+" ', "+age+")";
for(100){
stmt.executeUpdate(sql);
}
pstmt方式:
String sql = "insert into student(stuno,stuname) values(?, ?)";
pstmt = connection.prepareStatement(sql); //预编译sql
pstmt.setString(1,name);
pstmt.setString(2,age);
for(100){
stmt.executeUpdate(); //此时执行不需要编译,只需要执行就行
}
- 安全(有效的防止SQL注入)
sql注入:将客户输入的内容和开发人员的sql语句混为一体
stmt:存在SQL注入的风险
例如输入:
用户名:任意值 ' or 1=1 --
密码:任意值
分析:
select count(*) from login where uname =' "+name+" ' and upwd = ' "+pwd+" ';
等价于:select count(*) from login where uname =' 任意值 ' or 1=1 -- ' and upwd = ' "+pwd+" ';
等价于:select count(*) from login where uname =' 任意值 ' or 1=1 -- ';
等价于:select count(*) from login;
pstmt:防止SQL注入
select count(*) from login where uname =?and upwd =?;
三. JDBC总结(模板、八股文)
1. 模板总结
jdbc中,除了Class.forName()抛出ClassNotFoundException,其余方法全部抛出SQLException
2. CallableStatement
调用存储过程、存储函数
3. 处理CLOB[Text]/BLOB类型
四. JSP访问数据库
JSP就是在html里面嵌套的java代码,因此,java代码可以写在jsp中(<%… %>)
导包操作:
java项目:
1. jar复制到工程中
2. 右键该jar:build path ——>add to build path
web项目
3. jar复制到WEB-INF/lib下
login.jsp页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>通过数据库登录界面</title>
</head>
<body>
<form action="check.jsp" method="post">
用户名:<input type="text" name="uname"><br/>
密码:<input type="password" name="upwd"><br/>
<input type="submit" value="登录"><br/>
</form>
</body>
</html>
check.jsp页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="java.sql.*"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>检验数据库是否存在登录用户</title>
</head>
<body>
<%
String URL = "jdbc:mysql://localhost:3306/userdb?serverTimezone=GMT%2B8";
String username = "root";
String password = "root";
Connection con = null;
Statement stmt = null;
ResultSet rs = null;
try {
// 1. 导入驱动,加载具体的驱动类
Class.forName("com.mysql.cj.jdbc.Driver"); //加载具体的驱动类
// 2. 与数据库建立连接(通过DriverManager)
con = DriverManager.getConnection(URL, username, password);
// 3. 发送sql,执行命令(查询)
stmt = con.createStatement();
String name = request.getParameter("uname");
String pwd = request.getParameter("upwd");
String sql = "select count(*) from tb_admins where fd_username='"+name+"' and fd_password='"+pwd+"'";
//有这个人返回值就是1,没有返回值就是0
// 4. 执行SQL语句
rs = stmt.executeQuery(sql); //返回值表示查询的结果集
// 5. 处理结果
int count = -1;
if(rs.next()) //表示结果集的第一行
{
count = rs.getInt(1);//返回值就1个,所以只需要拿第一个就行
}
if(count>0){
out.println("登录成功");
}
else{
out.println("登录失败");
}
}
catch(Exception e)
{
e.printStackTrace();
}
finally {
try {
// 6. 关闭连接
if(rs!=null)
rs.close();
if(stmt!=null)
stmt.close();
if(con!=null)
con.close();
}catch(SQLException e) {
e.printStackTrace();
}
}
%>
</body>
</html>