JDBC(Java Database Connectivity)是一种用于Java编程语言的标准SQL数据库访问协议,它定义了一组接口和类,允许Java程序连接到各种类型的数据库管理系统。以下是关于JDBC的关键点:
目标:JDBC使得开发人员能够以一种统一的方式编写数据库应用程序,而无需关注底层特定数据库的细节。这样,同一个程序可以轻松地连接到不同的数据库,只要这些数据库提供了对应的JDBC驱动程序。
核心组件:
- DriverManager:管理数据库驱动的注册和建立数据库连接。
- Connection:代表与数据库的连接会话,用于创建Statement对象。
- Statement:用于执行静态的SQL语句并返回结果集(ResultSet)。
- PreparedStatement:预编译的SQL语句对象,比Statement更安全且性能更优,因为它允许参数化查询。
- CallableStatement:用于调用数据库中的存储过程。
- ResultSet:保存查询结果的数据表,可以通过它遍历获取每一行数据。
工作流程:
- 加载数据库驱动:通过Class.forName()动态加载数据库驱动类。
- 建立连接:使用DriverManager.getConnection()方法根据URL、用户名和密码建立数据库连接。
- 创建Statement:根据需要创建Statement、PreparedStatement或CallableStatement对象。
- 执行SQL:通过Statement对象执行SQL查询或更新。
- 处理结果:如果执行的是查询操作,则通过ResultSet处理返回的结果集。
- 关闭资源:操作完成后,确保关闭ResultSet、Statement和Connection以释放资源。
优势:
- 跨平台:由于Java的“一次编写,到处运行”特性,使用JDBC编写的数据库应用程序可以在任何支持Java的平台上运行。
- 灵活性:支持多种数据库,只需更换相应的JDBC驱动即可连接不同类型的数据库。
- 标准化:提供了一套标准的API,简化了数据库编程,提高了代码的可移植性。
public class JdbcDemo1 {
public static void main(String[] args) {
Connection connection = null;
ResultSet resultSet = null;
Statement statement = null;
try {
//0.注册驱动,告诉jdbc使用了哪个驱动程序
DriverManager.registerDriver(new Driver());
//1.建立连接---连接在jdbc中做了一个封装,叫做Connection
//需要传递的信息包含:url:指的是需要和哪台主机上面的哪个mysql软件里面的哪个db建立连接;username、password是建立连接所必须 的
//因为输入mysql -u root -p指令时,实际上是和本地的3306端口号上面的db建立连接,但是在jdbc中,需要给一个明确的地址
//url后面附着的这些东西是啥意思 characterEncoding=utf-8设置通讯的时候编码格式;useSSL=false其实指的是不加密;
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/60_db2?characterEncoding=utf-8&useSSL=false&useUnicode=true", "root", "123456");
//2.发送sql语句,需要一个叫做Statement对象来去处理
statement = connection.createStatement();
//编写sql语句
//3.接收返回结果
resultSet = statement.executeQuery("select * from student");
//4.处理数据,
// resultSet内部封装了一个类似于表格的东西,有一个游标默认指向的是第一行数据之前
//next表示的是将一个游标向下移动一行,顺势便获取到了当前行的数据
resultSet.next();
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
String aClass = resultSet.getString("class");
float chinese = resultSet.getFloat("chinese");
float english = resultSet.getFloat("english");
float math = resultSet.getFloat("math");
System.out.println("|" + id + " " + "|" + name + " " + "|");
} catch (SQLException e) {
throw new RuntimeException(e);
}finally {
//5.关闭连接
try {
if(connection != null){
//在命令行里面输入exit
connection.close();
}
if(resultSet != null){
resultSet.close();
}
if(statement != null){
statement.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
DriverManager
注册管理器,主要的功能有两个,一个是注册驱动;一个是获取连接。
需要特别注意的是,注册驱动时,导入的驱动,千万不要选择java.sql包开头的,那个是接口。需要选择mysql包
关于获取连接中url的写法:jdbc指的是jdbc协议;mysql指的是mysql子协议(表示的是就是当前数据库是mysql),如果后续我们使用jdbc去连接oracle,那么需要变更一下url地址;关于mysql的url地址建议大家能够背住。
DriverManager.registerDriver(new Driver());
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/60_db2?characterEncoding=utf-8&useSSL=false&useUnicode=true", "root", "123456");
Connection
当前客户端和数据库服务器建立的一个连接的抽象封装。比如使用cmd控制台,输入mysql -u root -p实际上便是建立了一个连接;当我们使用navicat连接数据库,那么也是建立了一个连接。
Connection是一个接口,实际上DriverManager.getConnection()方法运行之后会得到一个Connection对象的实现类,这里面使用的是接口指向子类实现的方式来使用的。
Statement
该对象专门用来和数据库进行通讯的。主要是用来传输sql语句的。
主要的方法有两个:1.executeQuery():执行查询操作 2.executeUpdate():执行增删改操作
还有一个close方法,释放资源。
补充了解:还有一个execute()做一个简单了解即可,如果不清楚执行的这条sql语句的类型,那么可以使用当前方法;如果方法的返回结果是一个true,则是查询;如果是false表示的是增删改操作。
结果集,就是数据库查询到的数据结果的封装体。结果集内部封装了一个类似于表格的数据。同时还会有一个游标指针,默认情况下,指向第一行数据之前。每移动一次next方法,那么游标便向下移动一行,此时便可以获取到当前行的数据。
如果需要获取数据,那么必须得调用next方法,移动游标才可以。
问题:如果希望获取全部的数据,应该怎么办???
resultSet.next()的返回结果为true或者false;
如果是true则表示的是后面还有其他行数据;如果是false,则没有其他行数据,也就是最后一行
//0.注册驱动,告诉jdbc使用了哪个驱动程序
DriverManager.registerDriver(new Driver());
//1.建立连接---连接在jdbc中做了一个封装,叫做Connection
//需要传递的信息包含:url:指的是需要和哪台主机上面的哪个mysql软件里面的哪个db建立连接;username、password是建立连接所必须 的
//因为输入mysql -u root -p指令时,实际上是和本地的3306端口号上面的db建立连接,但是在jdbc中,需要给一个明确的地址
//url后面附着的这些东西是啥意思 characterEncoding=utf-8设置通讯的时候编码格式;useSSL=false其实指的是不加密;
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/60_db2?characterEncoding=utf-8&useSSL=false&useUnicode=true", "root", "123456");
//2.发送sql语句,需要一个叫做Statement对象来去处理
statement = connection.createStatement();
//编写sql语句
//3.接收返回结果
resultSet = statement.executeQuery("select * from student");
//4.处理数据,
// resultSet内部封装了一个类似于表格的东西,有一个游标默认指向的是第一行数据之前
//next表示的是将一个游标向下移动一行,顺势便获取到了当前行的数据
while (resultSet.next()){
//此处使用和iterator有一点不太一样;iterator需要调用两个方法,resultSet只需要调用一个方法即可
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
System.out.println("|" + id + " " + "|" + name + " " + "|");
}
sql注入产生的原因是什么????把用户输入的命令参数当做了关键字来进行处理、解析。
解决办法其实非常的简单,那就是sql语句首先需要进行编译,形成数据库内部可以处理的指令,此时先不去带上用户的参数,先使用占位符占着,先进行编译,编译之后,再将用户的参数填充在对应的位置,此时,即便用户输入的参数中再包含drop等关键字,那么也不会有任何的功能了,因为已经没有编译步骤了。
mysql处理sql语句的执行过程
为什么我们输入select * from tb_name就可以查到对应的结果呢????
数据库会对上述的sql语句进行解析,然后需要去到硬盘上面去查找加载对应的文件资源,取出数据来。
public class MockLogin8 {
public static void main(String[] args) throws SQLException {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
//用scanner来模拟用户输入的用户名、密码
Scanner scanner = new Scanner(System.in);
String username = scanner.nextLine();
String password = scanner.nextLine();
connection = JdbcUtils.getConnection();
//之前我们使用的是statement对象,现在使用预编译sql对象
//此时获取到了一个预编译的sql对象,因为需要预编译,所以需要先把sql的模块确定,场景该预编译sql对象的时候需要sql语句
preparedStatement = connection.prepareStatement("select * from user where username = ? and password = ?");
//预编译之后,进行参数的填充处理
//需要注意的是:这里面的参数都是从1开始的
preparedStatement.setString(1, username);
preparedStatement.setString(2, password);
resultSet = preparedStatement.executeQuery();
//根据result.next返回结果是true还是false,判断用户名、密码是否匹配
if(resultSet.next()){
System.out.println("登录成功,用户名、密码匹配");
}else {
System.out.println("登录失败,用户名、密码错误");
}
} catch (SQLException e) {
throw new RuntimeException(e);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}finally {
JdbcUtils.close(connection, preparedStatement, resultSet);
}
}
}