1. 注册驱动DriverManger (驱动管理类)作用:
- 注册驱动
- 获取数据库连接
Class.forName("com.mysql.jdbc.Driver");
查看 Driver 类的源码:
static {
try {
DriverManager.registerDriver(new Driver());
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
}
}
提示:
- MySQL 5 之后的驱动包,可以省略注册驱动的步骤
- 自动加载 jar 包中的 META-INF/services/java.sql.Driver 文件中的驱动类
static Connection getConnection(String url,String user,String password)
- 参数:
- url 连接路径:
- 语法:jdbc:mysql://ip地址(域名):端口号/数据库名称?参数键值对1&参数键值对2......
- 示例:jdbc:mysql://127.0.0.1:3306/test
- 如果连接的是本机的 MySQL 服务器,并且 MySQL 服务器默认端口是3306,则 url 可以简写为:jdbc:mysql:///数据库名称?参数键值对
- 配置 useSSL=false 参数,禁用安全连接方式,解决警告提示
- user:用户名
- password:密码
public static void main(String[] args) throws Exception {
// 注册驱动
Class.forName("com.mysql.jdbc.Driver");
String url="jdbc:mysql://localhost/test";
String username="root";
String password="root";
// 获取连接
Connection connection = DriverManager.getConnection(url, username, password);
String sql="update account set money=2000 where id=1";
Statement statement = connection.createStatement();
// 执行 SQL 语句
int i = statement.executeUpdate(sql);
// 处理结果
System.out.println(i);
statement.close();
connection.close();
}
二、 Connection
1. 获取执行 SQL 的对象Connection (数据库连接对象)作用:
- 获取执行 SQL 的对象
- 管理事务
- 普通执行 SQL 对象
Statement createStatement()
- 预编译 SQL 的执行 SQL 对象:防止 SQL 注入
PreparedStatement preparedStatement(sql)
- 执行存储过程的对象
CallableStatament prepareCall(sql)2. 管理事务
- MySQL 事务管理
- 开启事务:BEGING; / START TRANSACTION;
- 提交事务:COMMIT;
- 回滚事务:ROLLBACK;
- MySQL 默认自动提交事务
- JDBC 事务管理:Connection 接口中定义了3个对应的方法
- 开启事务:setAutoCommit(boolean autoCommit); true 为自动提交事务;false 为手动提交食物,即为开启事务
- 提交事务:commit();
- 回滚事务:rollback();
public static void main(String[] args) throws Exception {
Class.forName("com.mysql.jdbc.Driver");
String url="jdbc:mysql://localhost/test";
String username="root";
String password="root";
Connection connection = DriverManager.getConnection(url, username, password);
String sql="update account set money=2000 where id=1";
Statement statement = connection.createStatement();
try {
// 开启事务
connection.setAutoCommit(false);
int i = statement.executeUpdate(sql);
System.out.println(i);
// 提交事务
connection.commit();
} catch (Exception e) {
// 回滚事务
connection.rollback();
e.printStackTrace();
}
statement.close();
connection.close();
}
三、 Statement
1. 执行 SQL 语句Statement 作用:
- 执行 SQL 语句
- int executeUpdate(sql) :执行 DML,DDL 语句
- 返回值:(1)执行 DML 语句返回受影响的行数。(2)DDL 语句执行后,执行成功也可能返回零
- ResultSet executeQuery(sql) :执行 DQL 语句
- 返回值:ResultSet 结果集对象
- 执行 DML 语句:
public static void main(String[] args) throws Exception {
Class.forName("com.mysql.jdbc.Driver");
String url="jdbc:mysql://localhost/test";
String username="root";
String password="root";
Connection connection = DriverManager.getConnection(url, username, password);
String sql="update account set money=2000 where id=1";
Statement statement = connection.createStatement();
// 执行 DML 语句受影响的行数
int count = statement.executeUpdate(sql);
if (count>0){
System.out.println("修改成功!");
}else {
System.out.println("修改失败!");
}
statement.close();
connection.close();
}
- 执行 DDL 语句:
public static void main(String[] args) throws Exception {
Class.forName("com.mysql.jdbc.Driver");
String url="jdbc:mysql://localhost/test";
String username="root";
String password="root";
Connection connection = DriverManager.getConnection(url, username, password);
String sql="create database test";
// String sql="drop database test"; 此条语句执行成功之后返回零
Statement statement = connection.createStatement();
// 执行 DDL 语句受影响的行数
int count = statement.executeUpdate(sql);
if (count>0){
System.out.println("修改成功!");
}else {
System.out.println("修改失败!");
}
// 所以执行 DDL 语句就不能使用这样的判断语句
statement.close();
connection.close();
}
四、 ResultSet
1. 封装 DQL 查询语句的结果ResultSet(结果集对象)作用
- 封装了 DQL 查询语句的结果
-
ResultSet statement.executeQuery(sql) :执行 DQL 语句,返回 ResultSet 对象
-
获取查询结果:
- boolean next() :(1)将光标从当前位置向前移动一行。(2)判断当前行是否为有效行
- 返回值:true :有效行,当前行有数据。 false :无效行,当前行没有数据。
- xxx getXxx(参数) :获取数据
- xxx:数据类型;如:int getInt(参数); String getString(参数);
- 参数:int :列的编号,从1开始。 String :列的名称。
- boolean next() :(1)将光标从当前位置向前移动一行。(2)判断当前行是否为有效行
-
使用步骤:
- 游标向下移动一行,并判断该行是否有数据:next();
- 获取数据:getXxx(参数);
// 循环判断游标是否是最后一行结尾
while(resultSet.next()){
// 获取数据
resultSet.getXxx(参数);
}
2. 简单使用
public static void main(String[] args) throws Exception {
Class.forName("com.mysql.jdbc.Driver");
String url="jdbc:mysql://localhost/test";
String username="root";
String password="root";
Connection connection = DriverManager.getConnection(url, username, password);
// 定义 SQL 语句
String sql="select * from account";
// 获取 statement 对象
Statement statement = connection.createStatement();
// 执行 SQL 语句
ResultSet resultSet = statement.executeQuery(sql);
// 处理结果,遍历 resultSet 中的所有数据
// 光标向下移动一行,并且判断当前行是否有数据
while (resultSet.next()){
// 获取数据 getXxx();
int id= resultSet.getInt(1);
String name= resultSet.getString(2);
double money= resultSet.getDouble(3);
// 或者如下写法:
// int id= resultSet.getInt("id");
// String name= resultSet.getString("name");
// double money= resultSet.getDouble("money");
System.out.println(id);
System.out.println(name);
System.out.println(money);
System.out.println("------");
}
// 关闭资源
resultSet.close();
statement.close();
connection.close();
}
3. 简单练习
查询 account 账户表数据,封装为 Account 对象中,并且存储到 ArrayList 集合中
public class Account {
private int id;
private String name;
private double money;
@Override
public String toString() {
return "Account{" +
" + id +
", name='" + name + ''' +
", money=" + money +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
}
public static void main(String[] args) throws Exception {
Class.forName("com.mysql.jdbc.Driver");
String url="jdbc:mysql://localhost/test";
String username="root";
String password="root";
Connection connection = DriverManager.getConnection(url, username, password);
String sql="select * from account";
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(sql);
// 创建集合
ArrayList list = new ArrayList<>();
while (resultSet.next()){
Account account = new Account();
int id= resultSet.getInt(1);
String name= resultSet.getString(2);
double money= resultSet.getDouble(3);
// 赋值
account.setId(id);
account.setName(name);
account.setMoney(money);
// 存入集合
list.add(account);
}
// 打印集合
System.out.println(list);
// 关闭资源
resultSet.close();
statement.close();
connection.close();
}
五、PreparedStatement
1. SQL 注入演示PreparedStatement 作用:
- 预编译 SQL 语句并执行:预防 SQL 注入问题
SQL 注入:SQL 注入是通过操作输入来修改事先定义好的 SQL 语句,用以达到执行代码对服务器进行攻击的方法
完成用户登录:
select * from user where username='张三' and password='123';
正常登录:
public void testLogin() throws Exception {
Class.forName("com.mysql.jdbc.Driver");
String url="jdbc:mysql://localhost/test";
String username="root";
String password="root";
Connection connection = DriverManager.getConnection(url, username, password);
// 接收用户输入 用户名和密码
String name="张三";
String pwd="123";
String sql="select * from user where username='"+name+"'and password='"+pwd+"'";
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(sql);
if (resultSet.next()){
System.out.println("登陆成功!");
}else {
System.out.println("登陆失败!");
}
resultSet.close();
statement.close();
connection.close();
}
SQL 注入:
public void testInject() throws Exception {
Class.forName("com.mysql.jdbc.Driver");
String url="jdbc:mysql://localhost/test";
String username="root";
String password="root";
Connection connection = DriverManager.getConnection(url, username, password);
// 接收用户输入 用户名和密码
String name="李四";
String pwd="' or '1' = '1";
String sql="select * from user where username'"+name+"'and password='"+pwd+"'";
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(sql);
if (resultSet.next()){
System.out.println("登陆成功!");
}else {
System.out.println("登陆失败!");
}
resultSet.close();
statement.close();
connection.close();
}
2. 预编译 SQL 语句并执行
- 获取 PreparedStatement 对象
// SQL 语句中的参数值,使用 ? 占位符替代 String sql="select * from user where username=? and password=?"; // 通过 Connection 对象获取,并传入对应的 SQL 语句 PreparedStatement preparedStatement=connection.preparedStatement(sql);
- 设置参数值
- PreparedStatement 对象:setXxx(参数1,参数2) :给 ? 赋值
- Xxx :数据类型;如 setInt(参数1,参数2)
- 参数: 参数1:? 的位置编号,从1开始; 参数2: ? 的值
- 执行 SQL
- executeUpdate(); executeQuery(); :不需要再传递 SQL
public void testLogin() throws Exception {
Class.forName("com.mysql.jdbc.Driver");
String url="jdbc:mysql://localhost/test";
String username="root";
String password="root";
Connection connection = DriverManager.getConnection(url, username, password);
// 接收用户输入 用户名和密码
String name="李四";
String pwd="1234";
// 定义 SQL 语句
String sql="select * from user where username=? and password=?";
// 获取 prepareStatement 对象
PreparedStatement preparedStatement = connection.prepareStatement(sql);
// 设置 ? 的值
preparedStatement.setString(1,name);
preparedStatement.setString(2,pwd);
ResultSet resultSet = preparedStatement.executeQuery();
if (resultSet.next()){
System.out.println("登陆成功!");
}else {
System.out.println("登陆失败!");
}
resultSet.close();
preparedStatement.close();
connection.close();
}
4. PreparedStatement 原理
(1)PreparedStatement 好处:
- 预编译 SQL ,性能更高
- 防止 SQL 注入:将敏感字符进行转义
- PreparedStatement 预编译功能开启:useServerPrepStmts=true; 添加到 URL 之后(使用 & 字符)
- 配置 MySQL 执行日志(重启 MySQL 服务后生效)
- 加入到 my.ini 文件中
log-output=FILE general-log=1 general_log_file="E:MySQLmysql.log" slow-query-log=1 slow_query_log_file="E:MySQLmysql_slow.log" long_query_time=2(2)PreparedStatement 原理
- 在获取 PreparedStatement 对象时,将 SQL 语句发送给 MySQL 服务器
进行检查,编译(这些步骤很耗时) - 执行时就不用再进行这些步骤了,速度更快
- 如果 SQL 模板一样,则只需要进行一次检查,编译
- 数据库连接池是个容器,负责分配,管理数据库连接(Connection)
- 它允许应用程序重复使用一个现有的数据库连接,而不是在重新建立一个
- 释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏
- 好处:①资源重用 ②提升响应速度 ③避免数据库连接遗漏
- 标准接口:DataSource
官方提供的数据库连接池标准接口,由第三方组织实现此接口
功能:获取连接 Connection getConnection(); - 常见的数据库连接池:① DBCP ② C3PO ③ Druid
- Druid(德鲁伊)
Druid 连接池是阿里巴巴开源的数据库连接池项目
功能强大,性能优秀,是 Java 语言最好的数据库连接池之一
- 导入 jar 包
- 定义配置文件
- 加载配置文件
- 获取数据库连接池对象
- 获取连接
配置文件:
driverClassName=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/test?characterEncoding=utf8&useServerPrepStmts=true&useSSL=false username=root password=root # 初始化连接数量 initialSize=5 # 最大连接数 maxActive=10 # 最大等待时间 maxWait=10004. 简单使用
public static void main(String[] args) throws Exception {
// 加载配置文件
Properties properties = new Properties();
properties.load(new FileInputStream("jdbc_01\src\druid.properties"));
// 获取连接对象
DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
// 获取数据库连接 Connection
Connection connection = dataSource.getConnection();
System.out.println(connection);
}
七、练习
1. 环境准备
(1)数据库表
create table brand(
id int primary key auto_increment,
brand_name varchar(20),
company_name varchar(20),
ordered int,
description varchar(100),
status int
);
insert into brand (brand_name, company_name, ordered, description, status)
VALUES ('三只松鼠','三只松鼠股份有限公司',5,'好吃不上火',0),
('华为','华为技术有限公司',100,'华为文化',1),
('小米','小米科技有限公司',50,'雷军-雷布斯',1);
select * from brand;
(2)实体类
public class Brand {
// 在实体类中,基本数据类型建议使用对应的包装类
private Integer id;
private String brandName;
private String companyName;
private Integer ordered;
private String description;
private Integer status;
@Override
public String toString() {
return "Brand{" +
" + id +
", brandName='" + brandName + ''' +
", companyName='" + companyName + ''' +
", ordered=" + ordered +
", description='" + description + ''' +
", status=" + status +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getBrandName() {
return brandName;
}
public void setBrandName(String brandName) {
this.brandName = brandName;
}
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
public Integer getOrdered() {
return ordered;
}
public void setOrdered(Integer ordered) {
this.ordered = ordered;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
}
2. 使用增删改查操作
(1)查询所有步骤:
- 获取 Connection
- 定义 SQL 语句
- 获取 PreparedStatement 对象
- 设置参数
- 执行 SQL 语句
- 处理结果
- 释放资源
@Test
public void testSelectAll() throws Exception {
// 加载配置文件
Properties properties = new Properties();
properties.load(new FileInputStream("jdbc_01\src\druid.properties"));
// 获取连接对象
DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
// 获取数据库连接 Connection
Connection connection = dataSource.getConnection();
// 定义 SQL 语句
String sql="select * from brand;";
// 获取 preparedStatement
PreparedStatement preparedStatement = connection.prepareStatement(sql);
// 执行 SQL 语句
ResultSet resultSet = preparedStatement.executeQuery();
// 处理结果 封装对象进入集合
List brands = new ArrayList<>();
Brand brand=null;
while (resultSet.next()){
// 获取数据
int id = resultSet.getInt("id");
String brandName = resultSet.getString("brand_name");
String companyName = resultSet.getString("company_name");
int ordered = resultSet.getInt("ordered");
String description = resultSet.getString("description");
int status = resultSet.getInt("status");
// 封装 Brand 对象
brand=new Brand();
brand.setId(id);
brand.setBrandName(brandName);
brand.setCompanyName(companyName);
brand.setOrdered(ordered);
brand.setDescription(description);
brand.setStatus(status);
// 装载集合
brands.add(brand);
}
System.out.println(brands);
// 关闭资源
resultSet.close();
preparedStatement.close();
connection.close();
}
(2)添加操作
@Test
public void testAdd() throws Exception {
// 接收页面提交的参数
String brandName="苹果";
String companyName="苹果公司";
int ordered=1;
String description="iPhone/Mas";
int status=1;
// 加载配置文件
Properties properties = new Properties();
properties.load(new FileInputStream("jdbc_01\src\druid.properties"));
// 获取连接对象
DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
// 获取数据库连接 Connection
Connection connection = dataSource.getConnection();
// 定义 SQL 语句
String sql="insert into brand(brand_name,company_name,ordered,description,status) values (?,?,?,?,?)";
// 获取 preparedStatement
PreparedStatement preparedStatement = connection.prepareStatement(sql);
// 设置参数
preparedStatement.setString(1,brandName);
preparedStatement.setString(2,companyName);
preparedStatement.setInt(3,ordered);
preparedStatement.setString(4,description);
preparedStatement.setInt(5,status);
// 执行 SQL 语句
int count = preparedStatement.executeUpdate();
// 处理结果
System.out.println(count>0);
// 关闭资源
preparedStatement.close();
connection.close();
}
(3)修改操作
@Test
public void testUpdate() throws Exception {
// 接收页面提交的参数
String brandName="苹果";
String companyName="苹果公司";
int ordered=1000;
String description="iPhone/Mas";
int status=1;
int id=4;
// 加载配置文件
Properties properties = new Properties();
properties.load(new FileInputStream("jdbc_01\src\druid.properties"));
// 获取连接对象
DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
// 获取数据库连接 Connection
Connection connection = dataSource.getConnection();
// 定义 SQL 语句
String sql="update brand set brand_name=?,company_name=?,ordered=?,description=?,status=? where id=?";
// 获取 preparedStatement
PreparedStatement preparedStatement = connection.prepareStatement(sql);
// 设置参数
preparedStatement.setString(1,brandName);
preparedStatement.setString(2,companyName);
preparedStatement.setInt(3,ordered);
preparedStatement.setString(4,description);
preparedStatement.setInt(5,status);
preparedStatement.setInt(6,id);
// 执行 SQL 语句
int count = preparedStatement.executeUpdate();
// 处理结果
System.out.println(count>0);
// 关闭资源
preparedStatement.close();
connection.close();
}
(4)删除操作
@Test
public void testDeleteById() throws Exception {
// 接收页面提交的参数
int id=4;
// 加载配置文件
Properties properties = new Properties();
properties.load(new FileInputStream("jdbc_01\src\druid.properties"));
// 获取连接对象
DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
// 获取数据库连接 Connection
Connection connection = dataSource.getConnection();
// 定义 SQL 语句
String sql="delete from brand where id=?;";
// 获取 preparedStatement
PreparedStatement preparedStatement = connection.prepareStatement(sql);
// 设置参数
preparedStatement.setInt(1,id);
// 执行 SQL 语句
int count = preparedStatement.executeUpdate();
// 处理结果
System.out.println(count>0);
// 关闭资源
preparedStatement.close();
connection.close();
}



