JDBC学习笔记
一、 基础概念:
-
java database connection
-
JDBC定义了操作所有关系型数据库的规则(接口)
-
每个数据库厂商提供自己数据库的实现类(
数据库驱动
) -
JDBC本质:
本质其实是(sun公司)定义的一套操作所有关系型数据库的规则,即接口。各个数据库厂商去实现这套接口,提供数据库驱动jar包。我们可以使用这套接口(JABC)编程,真正执行的代码是驱动jar包中的实现类
二、 快速入门
入门代码示例 :
public class JdbcDemo1 {
public static void main(String[] args) throws Exception {
// 1.导入驱动jar
// 2.注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 3.获取数据库连接对象
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/student", "root", "123456");
// 4. 定义sql语句
String sql = "update student set age = 11 where id = 1";
// 5. 获取执行sql语句的对象 Statement
Statement stmt = conn.createStatement();
// 6. 执行sql语句
int count = stmt.executeUpdate(sql);
// 7. 打印处理结果
System.out.println(count);
// 8. 释放资源
stmt.close();//释放执行sql语句的对象
conn.close();//释放连接数据库的对象
}
}
规范化代码:
* 处理异常
* 释放资源
* 判断结果
public class JDBCDemo2 {
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://localhost:3306/student", "root", "123456");
// 3. 定义sql语句
String sql = "insert into student value(null,'K',10)";
// 4. 获取执行sql的对象
stmt = conn.createStatement();
// 5. 执行sql语句
int count = stmt.executeUpdate(sql);//影响的行数
System.out.println(count);//打印
// 6. 处理结果
if(count > 0){
System.out.println("添加成功!");
}else{
System.out.println("添加失败!");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
if(stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
步骤:
1. 导入mysql的驱动jar包
-
jar包名:
mysql-connector-java-5.1.37-bin.jar
-
复制
mysql-connector-java-5.1.37-bin.jar
到项目的libs目录下(方便管理工具包) -
在项目中对包点击右键–>
Add as Library
(真正将jar包加入项目工作空间中)
2. 注册驱动
Class.forName("com.mysql.jdbc.Driver");
3. 获取数据库连接对象Connection
4.定义sql字符串存储sql语句
5. 获取执行sql语句的对象Statement
6. 执行sql语句,接受返回结果
7. 处理结果
8. 释放资源
三、 JDBC中的各个类和接口详解
1. DriverManager
: 数据库驱动管理对象
①、注册驱动
1. 作用:
告诉程序应该用哪个数据库的驱动jar包
static void registerDriver(Driver driver)
方法: 注册与给定的驱动程序 DriverManager
写代码则使用:Class.forName(“com.mysql.jdbc.Driver”); 加载名为com.mysql.jdbc.Driver的类进内存
com.mysql.jdbc.Driver包中的Driver类中写了静态代码块,调用了registerDriver()
方法,从而实现了驱动注册
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
2. 注意事项:
mysql 5 之后可以不用写注册驱动语句 ,因为jar包提供了一个java.mysql.Driver文件,里面写了类名com.mysql.jdbc.Driver,所以如果没有写注册驱动语句,则jar包会自动读取文件中的类名自动注册驱动。
所以mysql 5 之后的驱动jar包可以省略注册驱动的步骤
②、连接数据库
-
方法:
static Connection``getConnection(String url, String user, String password)
-
参数:
url
:指定连接的数据库路径
// 3.获取数据库连接对象 Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/student", "root", "123456"); 语法:jdbc:mysql://ip地址(域名):端口号/数据库名称 例子:jdbc:mysql://localhost:3306/student 拓展:如果连接的是本机的mysql服务器,并且mysql服务器默认端口是3306,则url可以简写为:jdbc:mysql:///student
user
:数据库用户名password
:数据库密码
2.Connection
:数据库连接对象
1. 功能:
①、获取执行sql语句的对象
Statement creatStatement()
PrepareStatement prepareStatement(String sql)
②、管理事务
-
开启事务:
void setAutoCommit(boolean autoCommit)
:调用该方法设置参数为false
,即开启事务。将此连接的自动提交模式设置为给定状态
-
提交事务:
void commit()
使自上次提交/回滚以来所做的所有更改都将永久性,并释放此
Connection
对象当前持有的任何数据库锁 -
回滚事务:
void
rollback()
撤消在当前事务中所做的所有更改,并释放此
Connection
对象当前持有的任何数据库锁
3.Statment
:执行sql语句的对象
1. 执行sql
①、(了解
)boolean
execute(String sql)
方法:
-
作用:
执行此
Statement
对象中的任意SQL语句,静态的sql语句:在sql字符串拼接好的时候就已经生成完整字符串
-
返回值:
true
:如果第一个结果是一个ResultSet
对象;
false
:如果第一个结果是更新计数或没有结果
②、int executeUpdate(String sql)
方法:
-
作用:
执行DML(
insert
、update
、delete
)语句(常用,修改表的数据) 执行DDL(
creat
,alter
,drop
)语句(不常用,因为表的结构设计一般在数据库中自己定义好了) -
返回值:
操作影响的行数,可以通过这个影响的行数来判断DML语句是否执行成功,返回值大于0,则代表成功,反之则失败
③、ResultSet executeQuery()
方法 :
-
作用:
执行DQL(select)查询语句
-
返回值:
一个包含查询产生的数据的ResultSet对象;从不null;
4.ResultSet
:结果集的对象,查询的结果
①、boolean
next()
方法: 将光标从当前位置向下移动一行
返回值:
如果新的当前行有效,则返回true,此时游标还没有到达最后一行的末尾
如果新的当前行无效,则返回false,此时游标在最后一行之后的一行
②、Xxx getXxx()
方法:获取相应数据类型的数据
有方法重载: 如:int getInt(参数)方法 String getString(参数)
int getInt(int columnIndex) 根据列的编号获取,编号从1开始,如getInt(3)
int getInt(String columnLabel) 根据列的名称获取,如getInt(“age”)
常用写法:
int rs = stmt.executeQuery(sql);
while(rs.next()){//当没有达到最后一行的末尾时
int age = rs.getInt("age");
System.out.println(age);
}
③、将查询返回的结果数据封装成JSON对象(重点
):
任务:将数据库中的student表中数据封装成JSON对象
数据库中的表:
库名称:student
表名称:student
实现代码:
student.class
package cn.itcast.doamin;
public class student {
private String name;
private int age;
private int id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public String toString() {
return "student{" +
"name='" + name + '\'' +
", age=" + age +
", id=" + id +
'}';
}
}
JDBCDemo6.class
package cn.itcast.jdbc;
import cn.itcast.doamin.student;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class JDBCDemo6 {
/**
* 测试findAll()方法
*
* @param args
*/
public static void main(String[] args) {
// 根据类JDBCDemo6,创建一个对象并调用其中的findAll()方法获取student数据
List<student> list = new JDBCDemo6().findAll();
System.out.println(list);
}
/**
* 查询所有student对象
*
* @return
*/
public List<student> findAll() {
List<student> list = null;//声明一个List,存放student对象
student stu = null;//声明student类的引用
Connection conn = null;
Statement stmt = null;
ResultSet res = null;
try {
// 1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2、获取数据库连接对象
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/student", "root", "123456");
// 3、定义sql语句
String sql = "select * from student";
// 4、获取sql语句执行对象
stmt = conn.createStatement();
// 5、执行sql语句
res = stmt.executeQuery(sql);
// 6、遍历结果集中的对象,封装对象,装载集合
// 创建list对象
list = new ArrayList<student>();
while (res.next()) {
int id = res.getInt("id");
String name = res.getString("name");
int age = res.getInt("age");
// 6.1、创建一个student对象
stu = new student();
// 6.2、给student对象赋值
stu.setId(id);
stu.setName(name);
stu.setAge(age);
// 6.3、将student对象存放到list中,装载集合
list.add(stu);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
// 7、释放资源
if (res != null) {
try {
res.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();
}
}
}
// 8、返回封装好的list
return list;
}
}
控制台输出
"C:\Program Files\Java\jdk-13.0.2\bin\java.exe" "-javaagent:D:\IntelliJ IDEA 2021.2.1\lib\idea_rt.jar=1989:D:\IntelliJ IDEA 2021.2.1\bin" -Dfile.encoding=UTF-8 -classpath "D:\IDEA 工作间\itcast\out\production\jdbc;D:\IDEA 工作间\itcast\jdbc\libs\mysql-connector-java-5.1.37-bin.jar" cn.itcast.jdbc.JDBCDemo6
[student{name='Kevin', age=100, id=1}, student{name='K', age=100, id=2}, student{name='K', age=10, id=20}, student{name='K', age=10, id=21}, student{name='K', age=10, id=22}, student{name='K', age=10, id=23}, student{name='K', age=10, id=24}, student{name='K', age=10, id=25}, student{name='K', age=10, id=26}, student{name='K', age=10, id=27}, student{name='K', age=10, id=28}, student{name='K', age=10, id=29}]
Process finished with exit code 0
5.(*重要)PrepareStatement
:执行sql语句的对象
①、SQL注入问题
:
在拼接sql语句时,有一些sql字符串的特殊字符参与字符串的拼接,会造成安全性的问题
1.用户名任意输入:adwa,输入密码:a’ or ‘1’ = '1
2.执行的sql语句为:
select * from user where username = 'adwa' and password = 'a' or '1' = '1'
②、解决:
使用PrepraeStatement对象来解决
③、预编译的sql语句:
字符串中的参数使用?作为占位符替代
④、步骤:
1. 导入mysql的驱动jar包
-
jar包名:
mysql-connector-java-5.1.37-bin.jar
-
复制
mysql-connector-java-5.1.37-bin.jar
到项目的libs目录下(方便管理工具包) -
在项目中对包点击右键–>
Add as Library
(真正将jar包加入项目工作空间中)
2. 注册驱动
Class.forName("com.mysql.jdbc.Driver");
3. 获取数据库连接对象Connection
4.定义sql字符串存储sql语句
注意
:用PrepareStatement对象执行sql语句- sql的参数用?作为占位符替代,如:
String sql = "select * from user where username = ? and password = ?";
5. 获取执行sql语句的对象PrepareStatement
PreparedStatement``prepareStatement(String sql)
创建一个PreparedStatement
对象,用于将参数化的SQL语句发送到数据库。
6. 给占位符?赋值
* 方法:setXxx(参数1,参数2)
* 参数1:占位符的位置编号,从1开始
* 参数2:占位符的值
6. 执行sql语句,接受返回结果,不需要传递sql语句作为参数
7. 处理结果
8. 释放资源
⑤、注意:
后期都用PrepareStatement对象进行增删改查的所有操作
- 可以防止sql注入
- 效率更高
四、抽取JDBC工具类:JDBCUtils
1. 目的:简化书写
2. 分析:
①、注册驱动也需要抽取
②、抽取一个方法获取连接对象
- 需求:不想传递参数(比较麻烦),还需要保证工具类的通用性
- 解决:配置文件
文件名:jdbc.prrperties
路径:src目录下
内容:
url=jdbc:mysql://localhost:3306/student user=root password=123456 driver=com.mysql.jdbc.Driver
③、抽取一个方法释放资源
3. 注意:
-
项目路径不能包含中文或者空格
,否则会报错:系统找不到类的路径 -
当jdbc.properties配置文件存放在src目录下时,需要先获取配置文件的路径,再进行文件加载
-
获取配置文件的内容时,括号里应该填属性名字符串
4. 项目目录结构:
5. 实现代码:
①、抽取的JDBCUtils工具类:
package cn.itcast.utils;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.sql.*;
import java.util.Properties;
public class JDBCUtils {
// 只有静态变量才能够被静态代码块和静态方法访问
private static String url;
private static String user;
private static String password;
private static String driver;
/**
* 静态代码块,只执行一次
* 实现配置文件jdbc.properties内容的读取,只需要读取一次即可拿到这些值
*/
static {
// 读取配置文件的内容
try {
/*
// 方法一:
// 1.获取当前类的类加载器
ClassLoader classLoader = JDBCUtils.class.getClassLoader();
// 2.使用类加载器加载资源文件,并将其转换为输入流
InputStream inputStream = classLoader.getResourceAsStream("jdbc.properties");
// 3.新建资源属性对象
Properties pro = new Properties();
// 4.加载资源文件
pro.load(inputStream);
// 5.打印资源的属性信息
System.out.println("资源文件的内容-->"+ pro.toString());
*/
// /*
// 方法二:
// 1. 获取文件的路径
// ①、用绝对路径
// String path = "D:\\IDEA_WorkSpace\\itcast\\jdbc\\src\\jdbc.properties";
// ②、用类加载器ClasssLoader获取 src 路径下的文件的方式
ClassLoader classLoader = JDBCUtils.class.getClassLoader();//获取当前类的类加载器(可以加载字节码文件进内存,可以获取src目录下资源文件的路径)
URL res = classLoader.getResource("jdbc.properties");//获取相对于src目录下指定文件名的资源对象,返回统一文件定位符,可以定位文件的绝对路径
String path = res.getPath();//获取资源的字符串路径
System.out.println("path-->" + path);
// 2. 创建集合对象
Properties pro = new Properties();
// 3. 加载文件
pro.load(new FileReader(path));
// 4. 打印资源的属性信息
System.out.println("资源文件的内容-->" + pro.toString());
// */
// 给类的成员变量赋值
url = pro.getProperty("url");
user = pro.getProperty("user");
password = pro.getProperty("password");
driver = pro.getProperty("driver");
// 注册驱动
Class.forName(driver);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 数据库连接
*
* @return 数据库连接对象
*/
public static Connection getConnection() throws SQLException {
// 常用写法为配置文件获取mysql配置好的参数
return DriverManager.getConnection(url, user, password);
}
/**
* 释放资源,实现重载
*/
public static void close(Statement stmt, Connection conn) {
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void close(ResultSet res, Statement stmt, Connection conn) {
if (res != null) {
try {
res.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();
}
}
}
}
②、JDBCDemo6测试类(封装数据库数据
):
package cn.itcast.jdbc;
import cn.itcast.doamin.student;
import cn.itcast.utils.JDBCUtils;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class JDBCDemo6 {
/**
* 测试findAll()方法
*
* @param args
*/
public static void main(String[] args) {
// 根据类JDBCDemo6,创建一个对象并调用其中的findAll()方法获取student数据
List<student> list = new JDBCDemo6().findAll2();
System.out.println(list);
}
/**
* 查询所有student表
* @return student对象数组
*/
public List<student> findAll2() {
List<student> list = null;//声明一个List,存放student对象
student stu = null;//声明student类的引用
Connection conn = null;
Statement stmt = null;
ResultSet res = null;
try {
1、注册驱动
// Class.forName("com.mysql.jdbc.Driver");
2、获取数据库连接对象
// conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/student", "root", "123456");
//替换成:
conn = JDBCUtils.getConnection();
// 3、定义sql语句
String sql = "select * from student";
// 4、获取sql语句执行对象
stmt = conn.createStatement();
// 5、执行sql语句
res = stmt.executeQuery(sql);
// 6、遍历结果集中的对象,封装对象,装载集合
// 创建list对象
list = new ArrayList<student>();
while (res.next()) {
int id = res.getInt("id");
String name = res.getString("name");
int age = res.getInt("age");
// 6.1、创建一个student对象
stu = new student();
// 6.2、给student对象赋值
stu.setId(id);
stu.setName(name);
stu.setAge(age);
// 6.3、将student对象存放到list中,装载集合
list.add(stu);
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
// 7、释放资源
// 替换成:
JDBCUtils.close(res,stmt,conn);
// if (res != null) {
// try {
// res.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();
// }
// }
}
// 8、返回封装好的list
return list;
}
}
5. 输出结果:
"C:\Program Files\Java\jdk-13.0.2\bin\java.exe" "-javaagent:D:\IntelliJ IDEA 2021.2.1\lib\idea_rt.jar=1583:D:\IntelliJ IDEA 2021.2.1\bin" -Dfile.encoding=UTF-8 -classpath D:\IDEA_WorkSpace\itcast\out\production\jdbc;D:\IDEA_WorkSpace\itcast\jdbc\libs\mysql-connector-java-5.1.37-bin.jar cn.itcast.jdbc.JDBCDemo6
path-->/D:/IDEA_WorkSpace/itcast/out/production/jdbc/jdbc.properties
资源文件的内容-->{password=123456, driver=com.mysql.jdbc.Driver, user=root, url=jdbc:mysql://localhost:3306/student}
[student{name='Kevin', age=100, id=1}, student{name='K', age=100, id=2}, student{name='K', age=10, id=20}, student{name='K', age=10, id=21}, student{name='K', age=10, id=22}, student{name='K', age=10, id=23}, student{name='K', age=10, id=24}, student{name='K', age=10, id=25}, student{name='K', age=10, id=26}, student{name='K', age=10, id=27}, student{name='K', age=10, id=28}, student{name='K', age=10, id=29}]
Process finished with exit code 0
五、JDBC连接数据库练习
1. 需求:
连接数据库db,查询user表,实现用户登录验证逻辑
2. 代码实现:
package cn.itcast.jdbc;
import cn.itcast.utils.JDBCUtils;
import java.sql.*;
import java.util.Scanner;
public class JDBCDemo7 {
public static void main(String[] args) {
// 1.键盘输入账号密码
Scanner in = new Scanner(System.in);
System.out.println("请输入用户名:");
String username = in.nextLine();
System.out.println("请输入密码:");
String password = in.nextLine();
boolean flag = new JDBCDemo7().login2(username, password);
if (flag) {
System.out.println("登录成功");
} else {
System.out.println("账号或密码错误");
}
}
/**
* 登录方法一:Statement对象,执行sql语句可能会产生sql注入问题,不安全
*/
public boolean login(String username, String password) {
if (username == null) {
System.out.println("请输入账号");
return false;
}
if (password == null) {
System.out.println("请输入密码");
return false;
}
// 获取配置的资源文件路径
Connection conn = null;
Statement stmt = null;//Statement对象
ResultSet res = null;
try {
// 1.注册驱动,获取数据库连接对象
conn = JDBCUtils.getConnection();
// 2.拼接字符串,定义sql语句
String sql = "select * from user where username = '" + username + "' and password = '" + password + "'";
System.out.println("sql语句-->" + sql);
// 3.创建执行sql语句的对象
stmt = conn.createStatement();
// 4.执行sql语句
res = stmt.executeQuery(sql);
// 5.如果查找到,则返回true,反之返回false
return res.next();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 6.释放资源
JDBCUtils.close(res, stmt, conn);
}
return false;
}
/**
* 登录方法二:PrepareStstement对象,占位符替代参数,解决sql注入问题
*/
public boolean login2(String username, String password) {
if (username == null) {
System.out.println("请输入账号");
return false;
}
if (password == null) {
System.out.println("请输入密码");
return false;
}
// 获取配置的资源文件路径
Connection conn = null;
PreparedStatement stmt = null;//PrepareStatement对象
ResultSet res = null;
try {
// 1.注册驱动,获取数据库连接对象
conn = JDBCUtils.getConnection();
// 2.拼接字符串
String sql = "select * from user where username = ? and password = ?";
// 3.创建执行sql的对象
stmt = conn.prepareStatement(sql);//传入sql语句
// 4.给sql语句赋值
stmt.setString(1, username);//赋值username
stmt.setString(2, password);//赋值password
System.out.println("sql语句-->" + sql);
// 5.执行sql语句,不用传sql语句
res = stmt.executeQuery();
// 6.如果查找到,则返回true,反之返回false
return res.next();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 7.释放资源
JDBCUtils.close(res, stmt, conn);
}
return false;
}
}
3. 控制台输出:
①、样例1:调用login()方法
"C:\Program Files\Java\jdk-13.0.2\bin\java.exe" "-javaagent:D:\IntelliJ IDEA 2021.2.1\lib\idea_rt.jar=5190:D:\IntelliJ IDEA 2021.2.1\bin" -Dfile.encoding=UTF-8 -classpath D:\IDEA_WorkSpace\itcast\out\production\jdbc;D:\IDEA_WorkSpace\itcast\jdbc\libs\mysql-connector-java-5.1.37-bin.jar cn.itcast.jdbc.JDBCDemo7
请输入用户名:
kevin
请输入密码:
kevin
sql语句-->select * from user where username = 'kevin' and password = 'kevin'
登录成功
Process finished with exit code 0
②、样例2:调用login()方法
"C:\Program Files\Java\jdk-13.0.2\bin\java.exe" "-javaagent:D:\IntelliJ IDEA 2021.2.1\lib\idea_rt.jar=5199:D:\IntelliJ IDEA 2021.2.1\bin" -Dfile.encoding=UTF-8 -classpath D:\IDEA_WorkSpace\itcast\out\production\jdbc;D:\IDEA_WorkSpace\itcast\jdbc\libs\mysql-connector-java-5.1.37-bin.jar cn.itcast.jdbc.JDBCDemo7
请输入用户名:
zhangsan
请输入密码:
123
sql语句-->select * from user where username = 'zhangsan' and password = '123'
登录成功
Process finished with exit code 0
③、样例3:(Statement对象执行sql可能会产生SQL注入问题)调用login()方法
"C:\Program Files\Java\jdk-13.0.2\bin\java.exe" "-javaagent:D:\IntelliJ IDEA 2021.2.1\lib\idea_rt.jar=4753:D:\IntelliJ IDEA 2021.2.1\bin" -Dfile.encoding=UTF-8 -classpath D:\IDEA_WorkSpace\itcast\out\production\jdbc;D:\IDEA_WorkSpace\itcast\jdbc\libs\mysql-connector-java-5.1.37-bin.jar cn.itcast.jdbc.JDBCDemo7
请输入用户名:
adwa
请输入密码:
a' or '1' = '1
sql语句-->select * from user where username = 'adwa' and password = 'a' or '1' = '1'
登录成功
Process finished with exit code 0
④、样例4:(PrepareStatement对象解决sql注入问题)调用login2()方法
"C:\Program Files\Java\jdk-13.0.2\bin\java.exe" "-javaagent:D:\IntelliJ IDEA 2021.2.1\lib\idea_rt.jar=5173:D:\IntelliJ IDEA 2021.2.1\bin" -Dfile.encoding=UTF-8 -classpath D:\IDEA_WorkSpace\itcast\out\production\jdbc;D:\IDEA_WorkSpace\itcast\jdbc\libs\mysql-connector-java-5.1.37-bin.jar cn.itcast.jdbc.JDBCDemo7
请输入用户名:
adwad
请输入密码:
a' or '1' = '1
sql语句-->select * from user where username = ? and password = ?
账号或密码错误
Process finished with exit code 0
六、JDBC控制事务:
1. 事务的概念:
一个包含多个步骤的业务操作。如果这个业务被事务管理,则这多个步骤要么同时成功,要么同时失败
2. 操作:
开启事务
提交事务
回滚事务
3.使用Connection对象
管理事务
-
开启事务:
void setAutoCommit(boolean autoCommit)
:调用该方法设置参数为false
,即开启事务。将此连接的自动提交模式设置为给定状态
在执行sql前开启事务
-
提交事务:
void commit()
使自上次提交/回滚以来所做的所有更改都将永久性,并释放此
Connection
对象当前持有的任何数据库锁当所有sql都执行完提交事务
-
回滚事务:
void
rollback()
撤消在当前事务中所做的所有更改,并释放此
Connection
对象当前持有的任何数据库锁在catch中回滚事务
示例代码:
package cn.itcast.jdbc;
import cn.itcast.utils.JDBCUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Scanner;
public class JDBCDemo8 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("请输入改变1的金额:");
int num1 = in.nextInt();
System.out.println("请输入改变1的金额:");
int num2 = in.nextInt();
Connection conn = null;
PreparedStatement stmt1 = null;
PreparedStatement stmt2 = null;
try {
// 1.连接数据库
conn = JDBCUtils.getConnection();
// 开启事务
conn.setAutoCommit(false);
// 2.定义sql(更新book表中的金额)
String sql1 = "update book set price = price + ? where bookName = 'C prime plus'";
String sql2 = "update book set price = price + ? where bookName = 'offer'";
// 3.定义执行sql的PrepareStatement对象
stmt1 = conn.prepareStatement(sql1);
stmt2 = conn.prepareStatement(sql2);
// 4.给占位符赋值
stmt1.setDouble(1, num1);
stmt2.setDouble(1, num2);
// 5.执行sql更新数据库
stmt1.executeUpdate();
// 制造异常
int a = 2 / 0;
stmt2.executeUpdate();
// 如果执行过程没有异常,则提交事务
conn.commit();
} catch (SQLException e) {
if (conn != null) {//如果连接不为空,则回滚事务
try {
conn.rollback();
} catch (Exception ex) {//捕获大一点的异常
ex.printStackTrace();
}
}
e.printStackTrace();
} finally {
// 6.释放资源
JDBCUtils.close(stmt1, conn);
JDBCUtils.close(stmt2, null);
}
}
}
七、数据库连接池技术
1. 概念:
其实就是一个容器(集合),存放数据库连接对象的容器
当系统初始化好后,容器被创建,容器会申请一些数据库连接对象,当用户来访问数据库时,从容器中获取数据库连接对象,用户访问完之后,会将连接对象归还给容器
2. 好处:
- 节约资源
- 用户访问高效
3. 实现:
①、标准接口:DataSource
-
获取连接对象的方法:`getConnection()`
-
归还连接对象的方法:如果连接对象是Connection是从连接池中获取的,那么调用`Connection.close()`方法时,则不是关闭连接,而是将连接对象归还到数据库连接池中,
②、拓展:
- 数据库连接池技术一般是通过数据库厂商实现
C3P0
:数据库连接池技术Druid
:数据库连接池技术,由阿里巴巴提供的
4、C3P0
:数据库连接技术
①、步骤:
-
1.导入数据库连接池jar包(
两个
)c3p0-0.9.5.2.jar
和mchange-commons-java-0.2.12.jar
-
2.导入数据库驱动jar包:
- 对项目点右键,new一个
Directory
文件夹,名称为libs
,将jar包ctrl+v到libs文件夹中 - 注意:需要对libs点击右键,Add as Library
- 对项目点右键,new一个
-
3.定义配置文件:
-
名称:
c3p0.properties 或者 c3p0-config.xml
-
路径1:直接将配置文件放到src目录下
-
-
4.获取数据库连接池对象
ComboPooledDataSource
-
(
*常用
)使用默认c3p0配置: 方法括号中不传参数,则会使用c3p0的默认配置 -
使用指定c3p0配置:在xml文件中执行配置名称,方法括号中传入指定的c3p0配置文件名
-
(
*重要
)由于指定了配置文件名称为c3p0.properties 或者 c3p0-config.xml
,所以系统会自动加载配置文件
-
-
5.常用的方法
1. 获取单个数据库连接对象:`getConnection()` 2. 归还数据库连接对象:`close()`
②、代码示例:
package cn.itcast.datasource.c3p0;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.sql.Connection;
import java.sql.SQLException;
public class C3P0Demo2 {
public static void main(String[] args) throws SQLException {
// 1.获取数据库连接池对象,系统会自动加载配置文件
ComboPooledDataSource ds = new ComboPooledDataSource();//使用默认c3p0配置
// ComboPooledDataSource ds = new ComboPooledDataSource("pointedC3P0");//使用指定的名称为:pointedC3P0的c3p0配置
// 2.获取多个数据库连接对象
for (int i = 1; i <= 10; i++) {
Connection conn = ds.getConnection();
System.out.println(i + " " + conn);
}
}
}
5. Druid
数据库连接池技术:
①、步骤:
- 1.导入jar包
- 2.定义配置文件:
- 是
properties
形式的配置文件 - 可以叫任意名称,可以放在任意目录下
- 是
- 3.获取数据库连接池对象:
- 4.通过工厂类来获取
DruidDataSourceFactory()
- 括号中的参数为
properties
或者Map
- (
*重要
)需要手动加载properties
配置文件
- 括号中的参数为
- 5.常用方法:
- 获取单个单个数据库连接对象:
getConnection()
- 归还单个数据库连接对象:
close()
- 获取单个单个数据库连接对象:
②、示例代码:
package cn.itcast.datasource.druid;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Properties;
public class DruidDemo1 {
public static void main(String[] args) throws Exception {
// 1.导入Druid的jar包
// 2.定义配置文件
// 3.加载配置文件
Properties pro = new Properties();
// 通过当前类加载器获取配置资源的文件路径
InputStream is = DruidDemo1.class.getClassLoader().getResourceAsStream("druid.properties");
// 加载配置文件
pro.load(is);
// 4.获取数据库连接池对象
DataSource ds = DruidDataSourceFactory.createDataSource(pro);
// 5.获取单个数据库连接对象
Connection conn = ds.getConnection();
System.out.println(conn);
}
}
6. 抽取Druid数据库连接池的JDBCUtils工具类
①、步骤:
-
定义一个JDBCUtils工具类
-
提供静态代码块加载配置文件,并且初始化连接池对象
-
提供可以给外界访问的方法:
-
DataSource getDataSource()
:返回数据库连接池对象 -
Connection getConnection()
:放回单个数据库连接对象 -
void close()
:释放资源、归还数据库连接对象
-
②、示例代码:
i、JDBCUtils工具类
package cn.itcast.utils;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/**
* Druid数据库连接池的工具类
*/
public class JDBCUtils {
// 定义数据库连接池对象
private static DataSource ds;
// 定义静态代码块,只执行一次
static {
try {
// 1.获取配置文件的路径
InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");
// 2.加载配置文件
Properties pro = new Properties();
pro.load(is);
// 3.获取数据库连接池对象
ds = DruidDataSourceFactory.createDataSource(pro);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 一、获取数据库连接池对象的方法
*/
public static DataSource getDataSource(){
return ds;
}
/**
* 二、获取单个数据库连接的对象
*/
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
/**
* 三、释放资源,归还单个连接对象
*/
public static void close(Statement stmt, Connection conn) {
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();//归还连接
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 释放资源,归还单个连接对象
*/
public static void close(ResultSet res, Statement stmt, Connection conn) {
if (res != null) {
try {
res.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();
}
}
}
}
ii. DruidDemo2测试类:
package cn.itcast.datasource.druid;
import cn.itcast.utils.JDBCUtils;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Scanner;
public class DruidDemo2 {
public static void main(String[] args) {
/**
* 演示Druid的JUDBUtils工具类的使用
*/
Scanner in = new Scanner(System.in);
System.out.println("请输入student的昵称:");
String name = in.nextLine();
Connection conn = null;
PreparedStatement stmt = null;
try {
// 1.获取单个数据库的连接对象
conn = JDBCUtils.getConnection();
// 2.定义sql语句
String sql = "insert into student value(null,?,15)";
// 3.获取sql执行对象
stmt = conn.prepareStatement(sql);
// 4.给占位符赋值
stmt.setString(1,name);
// 执行sql语句
int count = stmt.executeUpdate();
System.out.println(count);
} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCUtils.close(stmt,conn);
}
}
}
iii. 控制台输出:
"C:\Program Files\Java\jdk-13.0.2\bin\java.exe" "-javaagent:D:\IntelliJ IDEA 2021.2.1\lib\idea_rt.jar=4453:D:\IntelliJ IDEA 2021.2.1\bin" -Dfile.encoding=UTF-8 -classpath D:\IDEA_WorkSpace\jdbc\out\production\DatabaseConnection;D:\IDEA_WorkSpace\DatabaseConnection\libs\druid-1.0.9.jar;D:\IDEA_WorkSpace\DatabaseConnection\libs\c3p0-0.9.5.2.jar;D:\IDEA_WorkSpace\DatabaseConnection\libs\mchange-commons-java-0.2.12.jar;D:\IDEA_WorkSpace\DatabaseConnection\libs\mysql-connector-java-5.1.37-bin.jar cn.itcast.datasource.druid.DruidDemo2
请输入student的昵称:
lisi
10月 05, 2021 3:29:24 下午 com.alibaba.druid.pool.DruidDataSource info
信息: {dataSource-1} inited
1
Process finished with exit code 0
iv.数据库中的数据
八、Spring JDBC
1. 概念:
Spring框架对JDBC的简单封装,提供了一个JDBCTemplate对象简化JDBC的开发
2. 步骤:
-
1.导入jar包(5个)
注意:
添加到libs目录下,并且
Add as Library
JDBCTemplate需要依赖于mysql驱动jar包和Druid数据库连接池的jar包
-
2.创建JdbcTemplate对象。依赖于数据源DataSource
JdbcTemplate template = new JdbcTemplate(DataSource ds);
-
3.调用JdbcTemplate的方法来完成CRUD的操作
update()
:执行DML语句。增、删、改queryForMap()
:查询结果,将结果集封装成map集合queryForList()
:查询结果,将结果集封装成list集合query()
:查询结果,将结果集封装成JavaBean对象queryForObject()
:查询结果,将结果集封装为对象
3. 示例代码:
package cn.itcast.datasource.jdbctemplate;
import cn.itcast.utils.JDBCUtils;
import org.springframework.jdbc.core.JdbcTemplate;
/**
* JDBCTemplate入门学习
*/
public class JavaTemplateDemo1 {
public static void main(String[] args) {
// 1.导入jar包
// 2.创建JdbcTemplate对象,传参为数据源,即数据库连接池对象
JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
// 3.定义sql语句
String sql = "update student set name = ? where id = 2";
int count = template.update(sql, "haha");
System.out.println(count);
}
}
由于时间关系:以下为简略笔记,以后会再找个时间进行详细记录