目录
JDBC简介
JDBC定义
概述:JDBC通俗来讲就是使用java代码去操作数据库。
JDBC本质上是一个接口、接口中封装了操作数据库的方法、具体实现接口的类被我们成为数据库驱动类、
也就意味着我们将来要操作mysql数据库需要导入mysql的驱动包、操作oracle数据库需要导入oracle驱动包
驱动:指的就是实现jdbc接口规范实现类
JDBC常见接口和类
接口(类)名 | 描述 | 作用 |
---|---|---|
DriverManager | 驱动管理类 | 注册驱动 明确要访问数据类型 |
Conncation | 连接对象 | 与mysql 建立起通讯的桥梁 |
Statemnt | 可执行对象 | 创建推送sql到数据库服务器中载体 |
ResultSet | 结果集对象 | 执行sql数据库返回结果内容 |
JDBC快速入门
下载JDBC驱动
本门课我们以MySQL数据库为例,所以我们需要下载MySQL的JDBC驱动程序。
下载地址:https://dev.mysql.com/downloads/connector/j/5.1.html
目前常用的MySQL驱动有5.* 版本和 8.*版本,二者在使用时配置上略有不同,大家可以选择其中任意一个版本使用。
JDBC连接数据步骤
准备工作:创建项目并导入jar包
(1)在项目的根目录下创建一个Folder,通常用lib命名,将解压后的jar文件复制到该文件夹下。
(2)在Java项目中导入jar包,即构建jar文件路径。
方法一:
方法二:
编写代码
步骤:
1、注册驱动
2、获取连接
3、获取可执行对象
4、执行并获取结果
5、关闭资源
完整案例代码:
/*
* jdbc的入门案例
* 向user表中添加一条数据
* 全限定类名 = 包名+类名
*/
public class Jdbc_Demo01 {
public static void main(String[] args) throws Exception {
//1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2、获取连接
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/day08","root","root");
//3、获取可执行对象
Statement st = con.createStatement();
//4、执行并得到结果
String sql ="insert into user values(1,'张三',18)";
int row = st.executeUpdate(sql);
if(row>0) {
System.out.println("插入成功");
}else {
System.out.println("插入失败");
}
//5、关闭资源
st.close();
con.close();
}
}
JDBC的详解
注册驱动
Class.forName(“com.mysql.jdbc.Drvier”) 5.x 相当于明确了要连接数据库的类型
Class.forName(“com.mysql.cj.jdbc.Drvier”) 8.x
创建连接对象
Connaction con =DriverManger.getConnation(url,user,password);
1.参数url:要连接的数据库的地址
语法 协议:子协议://ip+端口/数据库名称
jdbc:mysql://localhost:3306/day08
1.如果我们连接的本地数据库、并且端口号是默认的3306那么 ip+端口可以省略
jdbc:mysql:///day08
2.假如你用驱动包是8.x版本 我们需要加入一段内容
jdbc:mysql:///day08?serverTimezone=utc
serverTimezone:utc 表示我们使用世界标准日期(以美国时间为准)
3.如果将来你使用jdbc插入数据数据出现乱码的时候这个时候你可以尝试这么设置
jdbc:mysql:///day08?unicode=true&characterEncoding=utf-8
2.参数user:访问数据库的用户名
3.参数password:访问数据的密码
4.建立与mysql数据库通话的桥梁
创建SQL编译器
Statement st =con.createStatement() 创建推送sql到数据库服务器的载体
执行SQL语句并返回结果
增删改 int executeUpdate(sql); 返回值表示受影响的行数
查询 ResultSet executeQuery(sql); 返回值查询到的内容
ResultSet中api
next() 判断当前行是否有数据如果有返回true,如果没有返回false
如果返回true我们就可以获取当前行的数据
get类型(索引) 通过索引指定列的值
get类型(列名) 通过列名称获取指定名称上列的值
释放资源
增删改关闭2个
可执行对象 statement.close()
连接对象 connaction.close()
查询关闭3个
结果集 ResultSet.close()
可执行对象 statement.close()
连接对象 connaction.close()
查询案例
单元测试
概述:单元测试指的是我们可以在不依靠main方法的程序单独让某个方法进行直接运行
@Test 测试方法
注意事项
1、要求方法没有返回值
2、要求方法没有参数
3、要求方法不能使用静态修饰
4、要求方法权限修饰符必须是public
@before 前置方法 在测试方法执行前先执行的方法
@after 后置方法 在测试方法执行后再执行的方法
代码示例
JDBC实现CRUD操作
package com.offcn.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import org.junit.Test;
/*
* JDBC 增删改查
*/
public class Jdbc_Demo03 {
/*
* 添加数据
*/
@Test
public void insertUser() throws Exception {
//1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2、获取连接
Connection con = DriverManager.getConnection("jdbc:mysql:///day08","root","root");
//3、获取可执行对象
Statement st = con.createStatement();
//4、执行并获取结果
String sql ="insert into user values(4,'白百何',18)";
int row = st.executeUpdate(sql);
if(row>0) {
System.out.println("插入成功");
}else {
System.out.println("插入失败");
}
//5、关闭资源
st.close();
con.close();
}
/*
* 修改数据
*/
@Test
public void updateUser() throws Exception {
//1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2、获取连接 ctrl+1
Connection con = DriverManager.getConnection("jdbc:mysql:///day08","root","root");
//3、获取可执行对象
Statement st = con.createStatement();
//4、执行并获取结果
String sql="update user set name='马保国',age=60 where uid =4";
int row = st.executeUpdate(sql);
if(row>0) {
System.out.println("更新成功");
}else {
System.out.println("更新失败");
}
//5、关闭资源
st.close();
con.close();
}
/*
* 删除数据
*/
@Test
public void deleteUser() throws Exception {
//1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2、获取连接
Connection con = DriverManager.getConnection("jdbc:mysql:///day08","root","root");
//3、获取可执行对象
Statement st = con.createStatement();
//4、执行并获取结果
String sql ="delete from user where uid = 1";
int row = st.executeUpdate(sql);
if(row>0) {
System.out.println("删除成功");
}else {
System.out.println("删除失败");
}
//5、关闭资源
st.close();
con.close();
}
/*
* 查询所有
*/
@Test
public void findAll() throws Exception {
//1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2、获取连接
Connection con = DriverManager.getConnection("jdbc:mysql:///day08","root","root");
//3、获取可执行对象
Statement st = con.createStatement();
//4、执行并获取结果
String sql ="select * from user";
ResultSet rs = st.executeQuery(sql);
while(rs.next()) {
//获取当前行内容
int uid = rs.getInt(1);
String name = rs.getString(2);
int age = rs.getInt(3);
System.out.println(uid+"\t"+name+"\t"+age);
}
//5、关闭资源
rs.close();
st.close();
con.close();
}
/*
* 查询一个用户
*/
@Test
public void findUser() throws Exception {
// 1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2、获取连接
Connection con = DriverManager.getConnection("jdbc:mysql:///day08", "root", "root");
// 3、获取可执行对象
Statement st = con.createStatement();
// 4、执行并获取结果
String sql ="select * from user where uid =2";
ResultSet rs = st.executeQuery(sql);
while(rs.next()) {
int uid = rs.getInt("uid");
String name = rs.getString("name");
int age = rs.getInt("age");
System.out.println(uid+"\t"+name+"\t"+age);
}
//5、关闭资源
rs.close();
st.close();
con.close();
}
}
PreparedStatement
登录功能SQL注入问题
概述:sql注入是一种常见网络攻击手段之一、它可以实现对于用户输入项的侵入、达到无密码跳过校验进行操作系统。
PreparedStatement是Statement的直接子接口,支持预编译技术,可以解决sql注入
原理 : 采用?占位符的方式对参数进行站位、将sql提前编译好、无论页面传递任何的内容、我们都认为传递是参数而不是作为sql关键字进行解析。就不会改变原有的sql结构
PreparedStatement 解决SQL注入问题
/*
* sql 注入的解决
*/
public class Jdbc_Demo05 {
public static void main(String[] args) throws Exception {
Scanner sc = new Scanner(System.in);
System.out.println("老弟请输入你的用户名");
String username = sc.nextLine();
System.out.println("老弟请输入你的密码");
String password = sc.nextLine();
//注册驱动
Class.forName("com.mysql.jdbc.Driver");
//获取连接
Connection con = DriverManager.getConnection("jdbc:mysql:///day08","root","root");
String sql ="select * from user1 where username =? and password =? ";
//获取可执行对象
PreparedStatement ps = con.prepareStatement(sql);
//给?号占位符赋值
ps.setString(1, username);
ps.setString(2, password);
//执行并获取结果
ResultSet rs = ps.executeQuery();
if(rs.next()) {
System.out.println("登录成功");
}else {
System.out.println("登录失败");
}
//关闭资源
rs.close();
ps.close();
con.close();
}
}
PreparedStatement与Statement的对比
1、PreparedStatement写法比较优雅、更加符合人们的开发思想、可读性非常好
2、PreparedStatement拥有预编译的能力
3、PreparedStatement执行效率要高于Statement
PreparedStatement的CRUD操作
package com.offcn.prepared;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import org.junit.Test;
public class Prepared_Demo01 {
/*
* 添加用户
*/
@Test
public void insertUser() throws Exception {
//1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2、获取连接
Connection con = DriverManager.getConnection("jdbc:mysql:///day08","root","root");
//3、获取可执行对象
String sql="insert into user values(?,?,?)";
PreparedStatement ps = con.prepareStatement(sql);
//给?占位符赋值
ps.setInt(1, 5);
ps.setString(2, "罗志祥");
ps.setInt(3, 18);
//4、执行并获取结果
int row = ps.executeUpdate();
if(row>0) {
System.out.println("添加成功");
}else {
System.out.println("添加失败");
}
//5、关闭资源
ps.close();
con.close();
}
/*
* 修改用户
*/
@Test
public void updateUser() throws Exception {
//注册驱动
Class.forName("com.mysql.jdbc.Driver");
//获取连接
Connection con = DriverManager.getConnection("jdbc:mysql:///day08","root","root");
//获取可执行对象
String sql="update user set name=?,age=? where uid=?";
PreparedStatement ps = con.prepareStatement(sql);
//给?号赋值
ps.setString(1, "孙悟空");
ps.setInt(2, 500);
ps.setInt(3, 2);
//执行并获取结果
int row = ps.executeUpdate();
if(row>0) {
System.out.println("修改成功");
}else {
System.out.println("修改失败");
}
//关闭资源
ps.close();
con.close();
}
/*
* 删除用户
*/
@Test
public void deleteUser() throws Exception {
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql:///day08","root","root");
String sql="delete from user where uid =?";
PreparedStatement ps = con.prepareStatement(sql);
ps.setInt(1, 3);
int row = ps.executeUpdate();
if(row>0) {
System.out.println("删除成功");
}else {
System.out.println("删除失败");
}
ps.close();
con.close();
}
/*
* 查询所有
*/
@Test
public void findAll() throws Exception {
//1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2、获取连接
Connection con = DriverManager.getConnection("jdbc:mysql:///day08","root","root");
//3、获取可执行对象
String sql="select * from user";
PreparedStatement ps = con.prepareStatement(sql);
//4、执行并获取结果
ResultSet rs = ps.executeQuery();
while(rs.next()) {
int uid = rs.getInt(1);
String name = rs.getString(2);
int age = rs.getInt(3);
System.out.println(uid+"\t"+name+"\t"+age);
}
//5、关闭资源
rs.close();
ps.close();
con.close();
}
/*
* 查询一条数据
*/
@Test
public void findUser() throws Exception {
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql:///day08","root","root");
String sql="select * from user where uid =?";
PreparedStatement ps = con.prepareStatement(sql);
ps.setInt(1, 4);
ResultSet rs = ps.executeQuery();
while(rs.next()) {
int uid = rs.getInt("uid");
String name = rs.getString("name");
int age = rs.getInt("age");
System.out.println(uid+"\t"+name+"\t"+age);
}
rs.close();
ps.close();
con.close();
}
}
JDBC工具类封装
工具类:简化 jdbc 操作、抽取重复性很高的代码到方法中达到方法的复用
1、获取连接方法
2、释放资源的方法
3、硬编码的解决 配置文件(在src创建db.properties)
Driver=com.mysql.jdbc.Driver
url=jdbc:mysql:///day08
user=root
password=root
/*
* JDBC工具类
*/
public class JDBCUtils2 {
private static String Driver;
private static String url;
private static String user;
private static String password;
//1、在整个类初始化过程中只会执行一次 2、优先级最高
static {
try {
//持久化属性集 key-value的集合
Properties pro = new Properties();//{}
//最终目标{Driver=com.mysql.jdbc.Driver,url=jdbc:mysql:///day08,user=root,password=root}
pro.load(new FileInputStream("src/db.properties"));
//根据key获取value
Driver = pro.getProperty("Driver");
url = pro.getProperty("url");
user = pro.getProperty("user");
password = pro.getProperty("password");
//注册驱动
Class.forName(Driver);
} catch (Exception e) {
e.printStackTrace();
}
}
/*
* 获取连接的方法
*/
public static Connection getConncation() throws SQLException {
return DriverManager.getConnection(url,user,password);
}
/*
* 关闭资源的方法
*/
public static void closeResource(ResultSet rs,Statement st,Connection con) {
if(rs!=null) {
try {
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(st!=null) {
try {
st.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(con!=null) {
try {
con.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}