目录
一、JDBC概念
JDBC本质:
JDBC好处:
二、JDBC快速入门步骤
三、JDBC API详解
DriverManger(驱动管理类)
Connection(数据库连接对象)
Statement(执行SQL语句)
ResultSet(结果集对象)
PreparedStatement(预编译SQL语句的对象)
一、JDBC概念
JDBC就是使用Java语言操作关系型数据库的一套API
全称:(Java DataBase Connectivity) Java数据库连接
JDBC本质:
官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口
各个数据库厂商去实现这套接口,提供数据库驱动jar包
我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类
JDBC好处:
各数据库厂商使用相同的接口,Java代码不需要针对不同数据库分别开发
可随时替代底层数据库,访问数据库的Java代码基本不变
二、JDBC快速入门步骤
0、创建工程,导入驱动jar包
1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
2、获取连接
Connection conn = DriverManager.getConnection(url, username, password);
3、定义SQL语句
String sql = "SQL语句";
4、获取执行SQL对象
Statement stat = conn.createStatement();
5、执行SQL
stat.executeUpdate(sql);
6、处理返回结果
7、释放资源
代码示例:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
/**
* JDBC快速入门
*/
public class JDBCDemo1he2 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2、获取连接:如果连接的是本机mysql并且端口是默认的3306,可以简化书写
String url = "jdbc:mysql:///db1?useUnicode=true&characterEncoding=utf8";
String username = "root";
String password = "199884lj";
Connection conn = DriverManager.getConnection(url, username, password);
//3、定义sql
String sql = "update stu set math = 90 where age = 55";
//4、获取执行sql的对象
Statement stat = conn.createStatement();
//5、执行sql
int count = stat.executeUpdate(sql);//受影响的行数
//6、处理结束
System.out.println(count);
//7、释放资源
stat.close();
conn.close();
}
}
三、JDBC API详解
DriverManger(驱动管理类)
管理JDBC驱动程序的基本服务。
作用:1、注册驱动 2、获取数据库连接
一、注册驱动
有此Driver文件可自动读取文件在,自动注册驱动
二、获取数据库连接
static Connaction getConnaction (String usl,String user,String password)
参数
1、url:连接路径
语法:jdbc:mysql://地址(域名):端口号/数据库名称?参数键值对1&参数键值对2...
示例:jdbc:mysql://127.0.0.1:3306/db1
细节:
如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,则usl可以简写为:jdbc:mysql:///数据库名称?参数键值对
2、user:用户名
3、password:密码
Connection(数据库连接对象)
与特定数据库连接(会话)。执行SQL语句并在连接的上下文中返回结果。
作用:1、获取执行SQL的对象 2、管理事务
1、获取执行SQL对象
普通执行SQL对象
Statement createStatement()
预编译SQL的执行SQL对象:防止SQL注入
PreparedStatement prepareStatement(sql)
执行存储过程的对象
CallableStatement prepareCall(sql)
2、事务管理
MySQL事务管理
开启事务:BEGIN;/START TRANSACTION;
提交事务:COMMIT;
回滚事务:ROLLBACK;
MySQL默认自动提交事务
JDBC事务管理:Connection接口中定义了3个对应的方法
开启事务:setAutoCommit(boolean autoCommit):true为自动提交事务;false为手动提交事务,即为开启事务
提交事务:commit()
回滚事务:rollback()
代码示例
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
/**
* JDBC API 详解:Connection
*/
public class JDBCDemo3_Connection {
public static void main(String[] args) throws Exception {
//1、注册驱动,在mysql的jar包下添加java.sql.Driver这个文件即可以省去手动注册驱动
// Class.forName("com.mysql.jdbc.Driver");
//2、获取连接:如果连接的是本机mysql并且端口是默认的3306,可以简化书写
String url = "jdbc:mysql:///db1?useUnicode=true&characterEncoding=utf8";
String username = "root";
String password = "xxxxxxxx";
Connection conn = DriverManager.getConnection(url, username, password);
//3、定义sql
String sql1 = "update stu set math = 300 where id = 1";
String sql2 = "update stu set math = 300 where id = 2";
//4、获取执行sql的对象
Statement stat = conn.createStatement();
try {
//开启事务
conn.setAutoCommit(false);
//5、执行sql
int count1 = stat.executeUpdate(sql1);//受影响的行数
//6、处理结束
System.out.println(count1);
//5、执行sql
int count2 = stat.executeUpdate(sql2);//受影响的行数
//6、处理结束
System.out.println(count2);
//提交事务
conn.commit();
} catch (Exception e) {
//回滚事务
conn.rollback();
e.printStackTrace();
}
//7、释放资源
stat.close();
conn.close();
}
}
执行结果:
Statement(执行SQL语句)
用于执行静态SQL语句并返回其生成的结果的对象。
作用:执行SQL语句
int executeUpdate(sql):执行DML、DDL语句
返回值:1、DML语句影响的行数 2、DDL语句执行后,执行成功也可能返回0
ResultSet executeQuery(sql):执行DQL语句
返回值:ResultSet结果集对象
代码示例:
import org.junit.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
/**
* JDBC API 详解:Statement
*/
public class JDBCDemo4_Statement {
/**
* 执行DML语句
*
* @throws Exception
*/
@Test
public void testDML() throws Exception {
//1、注册驱动,在mysql的jar包下添加java.sql.Driver这个文件即可以省去手动注册驱动
// Class.forName("com.mysql.jdbc.Driver");
//2、获取连接:如果连接的是本机mysql并且端口是默认的3306,可以简化书写
String url = "jdbc:mysql:///db1?useUnicode=true&characterEncoding=utf8";
String username = "root";
String password = "xxxxxxx";
Connection conn = DriverManager.getConnection(url, username, password);
//3、定义sql
String sql = "update stu set math = 90 where id=1";
//4、获取执行sql的对象
Statement stat = conn.createStatement();
//5、执行sql
int count = stat.executeUpdate(sql);//执行完DML语句,受影响的行数
//6、处理结束
//System.out.println(count);
if (count > 0) {
System.out.println("修改成功");
} else {
System.out.println("修改失败");
}
//7、释放资源
stat.close();
conn.close();
}
/**
* 执行DDL语句
* @throws Exception
*/
@Test
public void testDDDL() throws Exception {
//1、注册驱动,在mysql的jar包下添加java.sql.Driver这个文件即可以省去手动注册驱动
// Class.forName("com.mysql.jdbc.Driver");
//2、获取连接:如果连接的是本机mysql并且端口是默认的3306,可以简化书写
String url = "jdbc:mysql:///db1?useUnicode=true&characterEncoding=utf8";
String username = "root";
String password = "xxxxxxxx";
Connection conn = DriverManager.getConnection(url, username, password);
//3、定义sql
String sql = "drop database db2";
//4、获取执行sql的对象
Statement stat = conn.createStatement();
//5、执行sql
int count = stat.executeUpdate(sql);//执行完DDL语句,可能是0
//6、释放资源
stat.close();
conn.close();
}
}
运行结果:
ResultSet(结果集对象)
ResultSet作用:
1、封装了DQL查询语句的结果
ResultSet stmt.executeQuery(sql):执行DQL语句,返回ResultSet对象
获取查询结果
boolean next():1、将光标从当前位置向前移动一行 2、判断当前行是否为有效行
返回值:
1、true:有效行,当前行有数据
2、false:无效行,当前行没有数据
xxx getXxx(参数):获取数据
xxx:数据类型;如:int getInt(参数);String getString(参数)
参数
int:列的编号,从1开始
String:列的名称
代码示例:
import com.itheima.pojo.Account;
import org.junit.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
/**
* JDBC API 详解:Result
*/
public class JDBCDemo5_ResultSet {
/**
* 执行DQl语句
* @throws Exception
*/
@Test
public void testResultSet() throws Exception {
//1、注册驱动,在mysql的jar包下添加java.sql.Driver这个文件即可以省去手动注册驱动
// Class.forName("com.mysql.jdbc.Driver");
//2、获取连接:如果连接的是本机mysql并且端口是默认的3306,可以简化书写
String url = "jdbc:mysql:///db1?useUnicode=true&characterEncoding=utf8";
String username = "root";
String password = "xxxxxxx";
Connection conn = DriverManager.getConnection(url, username, password);
//3、定义sql
String sql = "select * from stu";
//4、获取statement对象
Statement stmt = conn.createStatement();
//5、执行sql
ResultSet rs = stmt.executeQuery(sql);
//处理结果,遍历rs中的所有数值
//6.1 光标向下移动一行,并且判断当前行是否有数据
// while(rs.next()){
// //6.2 获取数据 getXxx()
// int id = rs.getInt(1);
// String name = rs.getString(2);
//
// System.out.println(id);
// System.out.println(name);
//
// System.out.println("---------------");
// }
while(rs.next()){
//6.2 获取数据 getXxx()
int id = rs.getInt("id");
String name = rs.getString("name");
System.out.println(id);
System.out.println(name);
System.out.println("---------------");
}
//7、释放资源
rs.close();
stmt.close();
conn.close();
}
/**
* 查看account账户表数据,封装为Account对象中,并且存储到ArrayList集合中
* 1、定义实体类Account
* 2、查询数据,封装到Account对象中
* 3、将Account对象存入ArrayList集合中
*
*
* @throws Exception
*/
@Test
public void testResultSet2() throws Exception {
//1、注册驱动,在mysql的jar包下添加java.sql.Driver这个文件即可以省去手动注册驱动
// Class.forName("com.mysql.jdbc.Driver");
//2、获取连接:如果连接的是本机mysql并且端口是默认的3306,可以简化书写
String url = "jdbc:mysql:///db1?useUnicode=true&characterEncoding=utf8";
String username = "root";
String password = "xxxxxx";
Connection conn = DriverManager.getConnection(url, username, password);
//3、定义sql
String sql = "select * from account";
//4、获取statement对象
Statement stmt = conn.createStatement();
//5、执行sql
ResultSet rs = stmt.executeQuery(sql);
//创建集合
List<Account> list = new ArrayList<>();
while(rs.next()){
Account account = new Account();
//6.2 获取数据 getXxx()
int id = rs.getInt("id");
String name = rs.getString("name");
int money = rs.getInt("money");
//赋值
account.setId(id);
account.setName(name);
account.setMoney(money);
//存入集合
list.add(account);
}
System.out.println(list);
//7、释放资源
rs.close();
stmt.close();
conn.close();
}
}
运行结果:
PreparedStatement(预编译SQL语句的对象)
作用:预编译SQL语句并执行,预防SQL注入问题
SQL注入
SQL注入是通过操作输入来修改事先定义号的SQL语句,用以达到执行代码对服务器进行攻击的方法。
SQL注入演示:
import com.itheima.pojo.Account;
import org.junit.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
/**
* 用户登录
*/
public class JDBCDemo6_UserLogin {
@Test
public void testResultSet() throws Exception {
//2、获取连接:如果连接的是本机mysql并且端口是默认的3306,可以简化书写
String url = "jdbc:mysql:///db1?useUnicode=true&characterEncoding=utf8";
String username = "root";
String password = "199884lj";
Connection conn = DriverManager.getConnection(url, username, password);
//接收用户输入 用户名和密码
String name = "zhangsan";
String pwd = "2";
String sql = "select * from tb_user where username = '" + name + "' and password = '" + pwd + "'";
//获取stmt对象
Statement stmt = conn.createStatement();
//执行sql
ResultSet rs = stmt.executeQuery(sql);
//判断登录是否成功
if (rs.next()) {
System.out.println("登录成功");
} else {
System.out.println("登录失败");
}
//7、释放资源
rs.close();
stmt.close();
conn.close();
}
/**
* 演示SQL注入
* @throws Exception
*/
@Test
public void testLogin_Inject() throws Exception {
//2、获取连接:如果连接的是本机mysql并且端口是默认的3306,可以简化书写
String url = "jdbc:mysql:///db1?useUnicode=true&characterEncoding=utf8";
String username = "root";
String password = "199884lj";
Connection conn = DriverManager.getConnection(url, username, password);
//接收用户输入 用户名和密码
String name = "sdbabasdga";
String pwd = "'or'1'='1";
String sql = "select * from tb_user where username = '" + name + "' and password = '" + pwd + "'";
System.out.println(sql);
//获取stmt对象
Statement stmt = conn.createStatement();
//执行sql
ResultSet rs = stmt.executeQuery(sql);
//判断登录是否成功
if (rs.next()) {
System.out.println("登录成功");
} else {
System.out.println("登录失败");
}
//7、释放资源
rs.close();
stmt.close();
conn.close();
}
}
运行结果:
sql注入语句
select * from tb_user where username 'sdbabasdga' and password = ' ' or '1' = '1'
1、获取PreparedStatement对象
//SQL语句中的参数值,使用?占位符替代
String sql = "select * from tb_user where username = ? and password = ?";
//通过Connection对象获取,并传入对应的sql语句
PreparedStatement pstmt = conn.prepareStatement(sql);
2、设置参数值
PreparedStatement对象:setXxx(参数1,参数2):给?赋值
Xxx:数据类型:如setInt(参数1,参数2)
参数:
参数1:?的位置编号,从1开始
参数2:?的值
3、执行SQL
executeUpdate();/executeQuery();:不需要再传递sql
PreparedStatement好处:
1、预编译SQL,性能更高
2、防止SQL注入:将敏感字符进行转义
①PreparedStatement 预编译功能开启:useServerPrepStmts=true
②配置MySQL执行日志(重启mysql服务后生效)
log-output=FILE
general-log=1
general_log_file="D://mysql.log"
slow-query-log=1
slow_query_log_file="D://mysql_slow.log"
long_query_time=2
PrepareStatement原理:
1、在获取PreparedStatement对象时,将sql语句发送给mysql服务检查,编译(这些步骤很耗时)
2、执行时就不用再进行这些步骤,速度更快
3、如果sql模板一样,则只需要进行一次检查、编译
代码示例:
import org.junit.Test;
import java.sql.*;
/**
* API详解 PreparedStatement
*/
public class JDBCDemo7_PreparedStatement {
@Test
public void testPreparedStatement() throws Exception {
//2、获取连接:如果连接的是本机mysql并且端口是默认的3306,可以简化书写
String url = "jdbc:mysql:///db1?useUnicode=true&characterEncoding=utf8";
String username = "root";
String password = "xxxxxxxx";
Connection conn = DriverManager.getConnection(url, username, password);
//接收用户输入 用户名和密码
String name = "zhangsan";
String pwd = "123";
//定义sql
String sql = "select * from tb_user where username = ? and password = ?";
//获取stmt对象
PreparedStatement pstmt = conn.prepareStatement(sql);
//设置?的值
pstmt.setString(1,name);
pstmt.setString(2,pwd);
//执行sql
ResultSet rs = pstmt.executeQuery();
//判断登录是否成功
if (rs.next()) {
System.out.println("登录成功");
} else {
System.out.println("登录失败");
}
//7、释放资源
rs.close();
pstmt.close();
conn.close();
}
/**
* PreparedStatement原理
* @throws Exception
*/
@Test
public void testPreparedStatement2() throws Exception {
//2、获取连接:如果连接的是本机mysql并且端口是默认的3306,可以简化书写
String url = "jdbc:mysql:///db1?useUnicode=true&characterEncoding=utf8";
String username = "root";
String password = "xxxxxxx";
Connection conn = DriverManager.getConnection(url, username, password);
//接收用户输入 用户名和密码
String name = "zhangsan";
String pwd = "'or'1'='1";
//定义sql
String sql = "select * from tb_user where username = ? and password = ?";
//获取stmt对象
PreparedStatement pstmt = conn.prepareStatement(sql);
//设置?的值
pstmt.setString(1,name);
pstmt.setString(2,pwd);
ResultSet rs = null;
//执行sql
rs = pstmt.executeQuery();
//设置?的值
pstmt.setString(1,"aaa");
pstmt.setString(2,"bbb");
//执行sql
rs = pstmt.executeQuery();
//判断登录是否成功
if (rs.next()) {
System.out.println("登录成功");
} else {
System.out.println("登录失败");
}
//7、释放资源
rs.close();
pstmt.close();
conn.close();
}
}
运行结果: