JDBC
概念:
Java DataBase Connectivity Java数据库连接,Java语言操作数据库
JDBC的本质:
其实是官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口。
各个数据库厂商去实现这套接口,提供数据库驱动jar包。我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动 jar 包中的实现类。
eg. Person接口 Worker类
(父类引用指向子类对象:)Person p = new Worker();
p.eat(); 会调用实现类里的eat()方法,会产生一个多态的调用
步骤:
1.导入驱动 jar 包
2.注册驱动
3.获取数据库连接对象 Connection
4.定义 sql (语句)
5.获取执行 sql 语句的对象 Statement
6.执行sql,接受返回结果
7.处理结果
8.释放资源
eg.
1.导入驱动 jar 包
1.复制 mysql-connector-java-.......-bin.jar(驱动jar包)到项目的libs目录下
2.右键-->Add As Library (此操作才是真正的将这个jar包 加入到项目里来)
2.注册驱动
3.获取数据库连接对象 Connection
快捷键生成返回值对象 Ctrl+Alt+V
4.定义 sql (语句)
5.获取执行 sql 语句的对象 Statement
6.执行sql,接受返回结果
会返回一个int类型的值:
7.处理结果
8.释放资源
这里的返回值 1 表示影响的行数
可以看到 修改成功了:
详解各个对象:
1. DriverManager :驱动管理对象
2. Connection :数据库连接对象
3. Statement :执行 sql 的对象
4. ResultSet :结果集对象
5. PreparedStatement :执行 sql 的对象
1. DriverManager :驱动管理对象
功能:
1.注册驱动 :告诉程序该使用哪一个数据库驱动 jar 包
static void registerDriver(Driver driver):注册与给定的驱动程序 DriverManager
写代码使用:
Class.forName("com.mysql.cj.jdbc.Driver");
通过查看源码可以发现:在com.mysql.cj.jdbc.Driver类中,存在静态代码块
static {
try {
java.sql.DriverManager.registerDriver(new Driver() ) ;
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!")
}
}
注意:com.mysql.jdbc.Driver 和 com.mysql.cj.jdbc.Driver 都是MySQL JDBC驱动程序的类名,但对应不同的版本
com.mysql.jdbc.Driver是MySQL 5.x版本中的驱动程序类(已过时)
com.mysql.cj.jdbc.Driver是MySQL 8.0版本中的默认驱动程序类,支持最新的JDBC规范
2.获取数据库连接
方法:static Connection getConnection(String url , String user , String password)
参数:
url : 指定连接的路径
语法:jdbc : mysql : // ip地址(域名) : 端口号/数据库名称
例子:
jdbc:mysql://localhost:3306/db1
注:如果连接的是本机mysql服务器,并且mysql服务器默认端口是3306,则 url 可以简写为:jdbc : mysql : / / /数据库名称
user : 用户名
password : 密码
注: localhost : 本地服务器 本地回环地址:127.0.0.1 本地端口:3306
2. Connection :数据库连接对象
功能:
1.获取执行 sql 对象
Statement createStatement()
preparedStatement prepareStatement(String sql)
2.管理事务:
开启事务:
setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务
提交事务:commit()
回滚事务:rollback()
3. Statement :执行 sql 的对象
1.执行sql
1. boolean execute(String sql):可以执行任意的sql (了解)
2. int executeUpdate(String sql) :
执行DML(insert、update、delete)语句、DDL(create,alter,drop)语句
返回值:影响的行数,可以通过这个影响的行数判断DML语句是否执行成功
若返回值>0,则执行成功 ;反之,则失败
3. ResultSet executeQuery(String sql):执行DQL(select)语句
2.executeUpdate(String sql) 示例:
1.在表中添加一条记录 insert语句:
注:
1.在异常处理时,提供finally块,来执行任何清除操作(不管有没有异常被抛出、捕获,finally块都会被执行)
2.由于stmt,conn这两个对象都在try里,属于局部变量,释放资源时,无法获取到这两个对象,则要想释放资源,就要把它们的作用域提升到外面去,即: Statement stmt = null; Connection conn = null; 那么之后在try里边,给它们赋值时就不用再重复地声明了
2.修改表中的一条记录:
3.删除表中的一条记录:
可以看到 王五的这条记录已被删除:
4.执行 DDL语句:
(事实上什么都不会返回)
由此可见,表的创建也可以用executeUpdate()来执行
4. ResultSet :结果集对象,封装查询结果
next():游标向下移动一行
getXxx(参数):获取数据 (一次只能获取一行中一列的数据)
Xxx:代表数据类型 如:getInt()方法,会返回一个int型的值 int getInt()
String getString()
参数:
1. int:代表列的编号,从1开始 如:getString(1)
2. String:代表列名称 如:getDouble("math")
'
注意:上面的代码其实存在一个问题
ResultSet 正确的使用步骤应该如下:
1.游标向下移动一行
2.判断是否有数据
3.获取数据
boolean next():游标向下移动一行,判断当前行是否是最后一行末尾(是否有数据),如果是,则返回false;如果不是,则返回true
如果是最后一行末尾,则跳出循环;
如果不是,则获取数据
示例:
定义一个方法,查询stu2表的数据,将其封装为对象,然后装载集合,返回.
1.定义stu2类
2.定义方法 public List<stu2> findAll(){ }
3.实现方法 select * from stu2;
抽取JDBC工具类:
eg. JDBCUtils
目的:简化书写
分析:
1. 抽取 注册驱动
2. 抽取一个方法,获取连接对象
需求:不去传递参数(麻烦),并保证工具类的通用性
解决方法:通过使用配置文件
jdbc.properties
url=
user=
password=
配置文件:
3. 抽取一个方法,释放资源
尝试应用一下上面这个工具类:eg.
小练习:登录案例
需求:
1.通过键盘录入用户名和密码
2.判断用户是否登录成功
select * from user where username = " " and password = " " ;
如果这个sql有查询结果,则成功;反之,则失败
步骤:
1.创建一个数据库表 user
注意要修改一下配置文件中连接路径url中的数据库名称:
5. PreparedStatement :执行 sql 的对象
1.SQL注入问题:在拼接sql时,有一些sql的特殊关键字参与字符串的拼接。会造成安全性问题。eg.'a' or 'a'='a'
2.解决sql注入问题:使用PreparedStatement对象来解决
3.预编译SQL:参数使用?作为占位符
4.步骤:
1.导入驱动 jar 包
2.注册驱动
3.获取数据库连接对象 Connection
4.定义 sql
注意:sql的参数使用 ?作为占位符
eg. select * from user where username = ? and password = ?
5.获取执行 sql 语句的对象 PreparedStatement
Connection.prepareStatement(String sql)
6.给 ? 赋值:
setXxx(参数1,参数2)
参数1:?的位置编号 从1 开始
参数2:?的值
7..执行sql,接受返回结果,不需要传递sql语句
8.处理结果
9.释放资源
注意:后期都会使用PreparedStatement来完成增删改查的所有操作
因为:
1.可以防止SQL注入
2.效率更高
JDBC控制事务:
1.事务:一个包含多个步骤的业务操作。如果这个业务操作被事务管理,则这多个步骤要么同时成功,要么同时失败。
2.操作:
1.开启事务
2.提交事务
3.回滚事务
3.使用Connection对象来管理事务
开启事务:setAutoCommit(boolean autoCommit):调用该方法设置参数为false,即开启事务
在执行sql之前开启事务
提交事务:commit()
当所有sql都执行完,提交事务
回滚事务:rollback()
在catch中回滚事务
示例:
若有异常:eg.
可以看到,有异常后,事务回滚,数据库中这个表的对应数据未发生改变。