- DriverManager:驱动管理对象
- Connection:数据库连接对象
- Statement:执行sql的对象
- ResultSet:结果集对象
- PreparedStatement:执行sql的对象
DriverManager
驱动管理对象,主要功能如下:
- 注册驱动
- 获取数据库连接对象
1. 注册驱动
- 告诉程序该使用哪一个数据库驱动(填写jar包中Driver类的路径)
// 注册与给定的驱动程序 DriverManager
static void registerDriver(Driver driver) :
通过查看源码发现:在com.mysql.jdbc.Driver
类中存在静态代码块
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
注意:mysql5之后的驱动jar包可以省略注册驱动的步骤(jar包中有文件java.sql.Driver)。
写代码时使用此方法:
Class.forName("com.mysql.jdbc.Driver");
2. 获取数据库连接对象
方法:
static Connection getConnection(String url, String user, String password)
参数:
-
user:用户名
-
password:密码
-
url:指定连接的路径
jdbc:mysql://ip地址(域名):端口号/数据库名称
例如:
jdbc:mysql://localhost:3306/db3
细节:
- 如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,则url可以简写为:
jdbc:mysql:///数据库名称
Connection
数据库连接对象,主要功能如下:
- 获取执行sql 的对象
- 管理事务
1. 获取执行sql的对象
// 两种
Statement createStatement()
PreparedStatement prepareStatement(String sql)
2. 管理事务
- 开启事务:
调用该方法设置参数为false,即开启事务
setAutoCommit(boolean autoCommit) :
- 提交事务:
commit()
- 回滚事务:
rollback()
Statement
执行sql的对象,用于执行静态SQL语句并返回器生成的结果的对象。
- 可以执行任意的sql
boolean execute(String sql)
- 执行DQL(select)语句
// 返回的是结果集对象
ResultSet executeQuery(String sql)
- 执行DML(insert、update、delete)语句、DDL(create,alter、drop)语句
int executeUpdate(String sql)
返回的是影响的行数,判断DML语句是否执行成功:返回值大于零。DDL:只返回0。
功能演示
- 对account表进行添加一条记录
package cn.luis.demo1.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
/**
* @ClassName JDBCDemo2
* @Description 对表添加一条记录
* @Author L
* @Date 2020.01.17 21:31
* @Version 1.0
* @Remark account表 添加一条记录 insert 语句
**/
public class JDBCDemo2 {
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
try {
// 1.注册驱动(填写jar包中Driver类的路径)
Class.forName("com.mysql.jdbc.Driver");
// 2.定义sql
String sql = "insert into account values(null,'王五',3000)";
// 3.获取Connection对象
conn = DriverManager.getConnection("jdbc:mysql:///db3","root","root");
// 4.获取执行sql的对象,Statement
stmt = conn.createStatement();
// 5.执行sql
int count = stmt.executeUpdate(sql); // 影响的行数
// 6.处理结果
System.out.println("影响的行数:" + count);
if(count > 0) {
System.out.println("添加成功!");
} else {
System.out.println("添加失败!");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 7.释放资源
// stmt.close();
// 避免空指针异常(上面4.语句执行出错就会发生空指针异常)
if (stmt != null) { // 若为空,代表并未申请资源,也就不用释放了
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
// 避免空指针异常(上面2.语句执行出错就会发生空指针异常)
if (conn != null) { // 若为空,代表并未申请资源,也就不用释放了
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
结果:
影响的行数:1
添加成功!
- 创建一张Student表
package cn.luis.demo1.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
/**
* @Description 执行DDL语句
* @Author L
* @Date 2020.01.17 22:11
* @Version 1.0
* @Remark 创建一张表
**/
public class JDBCDemo5 {
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
try {
// 1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2.获取数据库连接对象
conn = DriverManager.getConnection("jdbc:mysql:///db3","root","root");
// 3.定义sql语句
String sql = "create table student (id int,name varchar(20))";
// 4.获取执行sql对象
stmt = conn.createStatement();
// 5.执行sql(影响的行数)
int count = stmt.executeUpdate(sql);
// 6.处理结果
System.out.println(count); // 0 没有返回值
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
} finally {
// 7.释放资源
/*
若程序还未执行到Stetement就抛出异常,此时stmt为null,
尚未申请资源,也就不用释放了,调用close()方法就会报错!
*/
if(stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
结果:
0
释放资源时需注意
若程序还未执行到Stetement就抛出异常,此时stmt为null,尚未申请资源,也就不用释放了,调用close()方法就会报错!【Connection类似】
if (stmt != null) {
...
}
ResultSet
结果集对象,用于封装查询结果
获取封装数据的两个步骤
-
游标向下移动一行
返回值:布尔值,判断当前行是否是最后一行末尾(是否有数据)。
如果是,则返回false,如果不是则返回true
boolean next():
-
获取数据
Xxx:代表数据类型 如: getInt() 、getString()
-
参数
- int:代表列的编号,从1开始 如: getString(1)
- String:代表列名称。 如: getDouble(“表的列名”)
getXxx(参数):
使用步骤
- 游标向下移动一行
- 判断该行是否有数据
- 获取数据
- 代码演示:
/*
6.处理结果,省略其他部分代码
*/
// 6.1让光标向下移动一行,循环判断游标是否到达最后一行末尾,并判断是否有数据
while(rs.next()) {
// 6.2获取数据
int id = rs.getInt(1);
String name = rs.getString("name");
double balance = rs.getDouble("balance");
System.out.println(id + "---" + name + "---" + balance);
}
// 释放rs资源
案例
定义一个方法,查询emp表的数据将其封装为对象,然后装载集合,打印。
- 定义
Emp
类 - 定义JDBC类
- 定义方法
public List<Emp> findAll(){}
- 注册驱动
- 获取连接
- 定义SQL语句
- 获取执行SQL对象
- 遍历结果集,创建EMP对象,封装数据
- 装载List集合
- 定义方法
代码演示:
- Emp实体类:略
- JDBC类
package cn.luis.demo1.jdbc;
import cn.luis.demo2.domain.Emp;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
/**
* @ClassName JDBCDemo9
* @Description 定义一个方法
* @Author L
* @Date 2020.01.18 10:34
* @Version 1.0
* @Remark 查询emp表中数据将其封装为对象,然后装载集合,返回。
**/
public class JDBCDemo9 {
public static void main(String[] args) {
List<Emp> list = new JDBCDemo9().findALL();
System.out.println(list.size());
for (Emp emp : list) {
System.out.println(emp);
}
}
/**
* @Author Lius
* @Description 查询所有emp对象
* @Date 10:36 2020.01.18
* @Param []
* @Return java.util.List<cn.luis.demo2.domain.Emp>
**/
public List<Emp> findALL() {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
List<Emp> list = null;
try {
// 1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2.获取连接
conn = DriverManager.getConnection("jdbc:mysql:///db2", "root", "root");
// 3.定义sql
String sql = "select * from emp";
// 4.获取执行sql对象
stmt = conn.createStatement();
// 5.执行sql语句
rs = stmt.executeQuery(sql);
// 6.遍历结果集,封装对象,装载集合
// 创建emp对象
Emp emp = null;
list = new ArrayList<>();
while (rs.next()) {
// 6.处理结果("id"):要和数据库中的名称相同!!!
int id = rs.getInt("id");
String ename = rs.getString("ename");
int job_id = rs.getInt("job_id");
int mgr = rs.getInt("mgr");
Date joindate = rs.getDate("joindate");
double salary = rs.getDouble("salary");
double bonus = rs.getDouble("bonus");
int dept_id = rs.getInt("dept_id");
// 创建emp对象
emp= new Emp();
emp.setId(id);
emp.setEname(ename);
emp.setJob_id(job_id);
emp.setMgr(mgr);
emp.setJoindate(joindate);
emp.setSalary(salary);
emp.setBonus(bonus);
emp.setDept_id(dept_id);
// 装载集合
list.add(emp);
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
} finally {
if(rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return list;
}
}·
结果:
15
Emp{id=1001, ename='孙悟空', ... salary=10000.0, bonus=0.0, dept_id=20}
Emp{id=1002, ename='卢俊义', ... salary=16000.0, bonus=3000.0, dept_id=30}
...
PreparedStatement
执行sql的对象,解决sql注入问题
SQL注入问题
在拼接sql时,有一些sql的特殊关键字参与字符串的拼接。会造成安全性问题 【静态sql易发生】
例如
-
输入用户随便,输入密码:a’ or ‘a’ = 'a
此时
sql
语句永远成立,会显示所有数据
select * from user where username = 'fhdsjkf' and password = 'a' or 'a' = 'a'
解决sql注入问题
使用PreparedStatement对象来解决
- 预编译的SQL:参数使用
?
作为占位符
select * from user where username = ? and password = ?;
步骤
- 导入驱动jar包
mysql-connector-java-5.1.37-bin.jar
- 注册驱动
- 获取数据库连接对象
Connection
- 定义
sql
select * from user where username = ? and password = ?;
- 获取执行sql语句的对象
PreparedStatement
PreparedStatement pstmt = conn.prepareStatement(sql);
-
给
?
赋值:方法:setXxx(参数1,参数2)
参数1:
?
的位置编号,从1 开始;参数2:
?
的值。
pstmt.setString(1,username);
pstmt.setString(2,password);
-
执行sql,接收返回结果
不需要传递sql语句,在获取
PreparedStatement
已传入
pstmt.executeQuery();
-
处理结果
-
释放资源
注意
后期都会使用PreparedStatement来完成增删改查的所有操作
- 可以防止SQL注入
- 效率更高
代码实现
package cn.luis.demo1.jdbc;
import cn.luis.demo2.domain.Emp;
import cn.luis.demo3.util.JDBCUtils;
import java.sql.*;
import java.util.List;
import java.util.Scanner;
/**
* @Description 定义一个方法
* @Author L
* @Date 2020.01.18 10:34
* @Version 1.0
* @Remark
**/
public class JDBCDemo12 {
public static void main(String[] args) {
// 1.键盘录入
Scanner sc = new Scanner(System.in);
System.out.print("输入用户名:");
String username = sc.next();
System.out.print("输入密码:");
String password = sc.next();
// 2.调用方法
boolean flag = new JDBCDemo12().login(username, password);
// 3.判断结果
if(flag) {
System.out.println("登陆成功!");
} else {
System.out.println("用户名或密码错误!");
}
}
/**
* @Author Lius
* @Description 练习 登录方法,使用PreparedStatement实现
* @Date 10:36 2020.01.18
* @Param []
* @Return java.util.List<cn.luis.demo2.domain.Emp>
**/
public boolean login(String username, String password) {
if(username == null || password == null) {
return false;
}
// 连接数据库
// 1.获取连接
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
// 1.获取连接
conn = JDBCUtils.getConnection();
// 2.定义sql
String sql = "select * from user where username = ? and password = ?";
// 3.获取执行sql对象
pstmt = conn.prepareStatement(sql);
// 4.给 ? 赋值
pstmt.setString(1,username);
pstmt.setString(2,password);
// 5.执行sql语句
rs = pstmt.executeQuery();
// 6.判断
return rs.next(); // 如果有下一行,则返回true
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.close(rs,pstmt,conn);
}
return false;
}
}
结果:
输入用户名:zhangsan
输入密码:123
登陆成功!