今天给大家分享一下 jdbc原理,每一步都会给大家讲到,相信大家看完这个之后一定会有新的收获!
1 jdbc 是什么 ?
jdbc全称为:java database connectivity (java和 数据库的连接 )
Sun公司为了简化、统一对数据库的操作,定义了一套java操作数据库的接口的规范,称之为JDBC。
应该知道什么是jdbc: 哦 原来是Sun公司为了统一对数据库的操作,从而定义的操作数据库接口规范呀!
总结jdbc: 数据库接口规范
2 jdbc 常用类和接口
JDBC有关的类:都在java.sql 和 javax.sql 包下
DriverManger:数据库驱动类,不同的数据库有不同的数据库驱动,用来注册驱动。
Connection:数据库连接,建立一个操作数据库的连接。
Statement:数据库操作,向数据库发送sql语句
ResultSet:结果集,Statement执行完sql返回的结果,封装在了ResultSet中
应该知道每一个类的作用
总结:jdbc是java程序和数据之间的桥梁
DriverManger 负责加载数据库驱动,确认是哪个数据库
Connection 负责建立java与数据之间连接,相当于搭桥
Statement 负责传输sql语句,相当于一辆车去拉货
ResultSet 结果集,相当于车拉过来的货物
3 快速入门
提前导入mysql 数据库驱动,可以去MySQL :: Download Connector/J 下载驱动
public static void main(String[] args) throws Exception {
//1.首先注册驱动
DriverManager.registerDriver(new Driver());
//2.获取连接
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/data01", "root", "123");
//3.创建statement对象,用于向数据库发送sql语句
Statement statement = connection.createStatement();
//4.发送sql语句
String sql = "select * from user";
ResultSet resultSet = statement.executeQuery(sql);
//5.遍历
while(resultSet.next()){
System.out.println(resultSet.getString("username"));
}
//6.释放资源:先开后关,后开先关
resultSet.close();
statement.close();
connection.close();
}
总结:须会手动下载驱动,自己加载驱动包,可以自己敲出以上代码,能够访问到数据库数据
4 jdbc详解
4.1DriverManager 驱动管理
以上注册驱动有点问题,通过打开源码看到
发现mysql 驱动包里已注册过mysql驱动,我们相当于又注册了一次。发现重复注册问题,我们可以使用反射方法直接使用已注册的驱动
DriverManager.registerDriver(new Driver());替换为 Class.forName("com.mysql.jdbc.Driver");
总结: 知道为什么注册驱动时候 要写成这样 Class.forName("com.mysql.jdbc.Driver");
4.2 Connection 数据库连接
程序与数据库的连接
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/data01", "root", "123");
作用:URL用于标识数据库的位置,程序员通过URL地址告诉JDBC程序连接哪个数据库
语法格式:jdbc:mysql:// localhost:3306/数据库名?key=value
简写形式:jdbc:mysql:///数据库名 等价于 jdbc:mysql://localhost:3306/数据库名
简写要求:必须是本地数据库,端口号必须是3306
常用属性:useUnicode=true&characterEncoding=UTF-8(不常使用)
解决问题:中文乱码异常
举例:jdbc:mysql://localhost:3306/day07?useUnicode=true&characterEncoding=utf8
总结:须记住URL书写格式
4.3 Statement 详解
需知以下三者区别
1 Statement.executeQuery(sql); 只可执行查询,返回ResulSet结果集
2 Statement.executeUpdate(sql); 只可执行增删改,返回受影响的行数
3 Statement.execute(sql) ; 返回true 说执行的是查询,返回false 说明执行的是增删改
如何取值,看代码
if(flag){
System.out.println("执行的是select");
ResultSet resultSet = statement.getResultSet();
while(resultSet.next()){
System.out.println(resultSet.getString("id"));
}
}else{
System.out.println("执行的是非update语句");
int count = statement.getUpdateCount();
System.out.println("sql语句影响的行数为"+count);
}
4.4 ResultSet 为什么用while
结果集其实就是一张表。所以再java中怎么遍历这个表呢?首先,resultSet结果集有一个光标,一开始这个光标处于数据表的第一行数据之前。而我们可以通过ResultSet.next()方法将光标下移。如果说,光标所指向的当前行有数据的话,那么会返回true,如果没有值的话,那么会返回false。基于这样一个情况,我们可以通过
总结
While(ResultSer.next)的方式对ResultSet做遍历。一直到光标所在行没有数据的话,结束遍历。
4.5 资源释放
finally{
if(rs != null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
rs = null;
}
if(st != null){
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
st = null;
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
总结:
看似一段简单的代码 需要知道的几个点
1. 不能把几个释放资源放到一个try块内,避免第一个错误,后两个释放不了的问题
2. 判断一下是否为空,避免不必要的释放
3. 释放完资源后,要赋空值,以确保正常的垃圾回收
4 释放职员要放在 finally 块中,保证任何情况都能正常释放掉资源
5 sql 注入问题
什么是sql注入?
没有对用户输入进行充分检查,而SQL又是拼接而成,在用户输入参数时,在参数中添加一些SQL 关键字,达到改变SQL运行结果的目的,也可以完成恶意攻击。
举例,这是某人账户是admin 密码是123, 他以下这样输入
String username = "admin' -- ";
String password = "1234";
在数据库中看到的是
可以看到 在密码错误的情况下,数据库账户后面已经被注释掉了,依然可以正常长查询到结果
preparedStatement 解决sql注入问题
PreparedStatement是Statement的子接口,它的实例对象可以通过调用Connection.preparedStatement(sql)方法获得
PreparedStatement 采用预编译技术,可以对sql中特殊的字符含义转义,转成没有意义的字符
sql语句中需要参数。使用?进行占位。
String username = "admin' -- ";
String password = "1234";
Connection con = null;
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
//获取连接
con = JdbcUtil.getConnection();
//使用preparedStatement对象解决sql注入问题
String sql = "select count(*) from user where username=? and password=?";
//创建preparedStatement对象
statement = con.prepareStatement(sql);
//sql语句已经被编译过了。
//设置参数
statement.setString(1, username);
statement.setString(2,password);
//执行sql语句。注意,不能再传入sql参数
resultSet = statement.executeQuery();
int count = 0;
while(resultSet.next()){
count = resultSet.getInt(1);
}
if(count==1){
System.out.println("登录成功");
}else{
System.out.println("登录失败");
}
}
成功解决sql注入问题
祝大家每天技术有新的突破!
var code = "ba0ca909-d35a-4025-8615-07e44dcb05f8"