JDBC: 即Java Database Connectivity,java数据库连接。是一种用于执行SQL语句的Java API,
它是Java中的数据库连接规范。这个API由 java.sql.*,javax.sql.* 包中的一些类和接口组成,
它为Java开发人员操作数据库提供了一个标准的API,可以为多种关系数据库提供统一访问。
产生的原因:
MySQL、Oracle、SQL server 这些数据库都提供自己的 API 来支持程序员实现自己的客户端来完成一些增删改查功能, 没有业界统一的标准,Java 当然不乐意了, 因为 Java 诞生就是为了跨平台的。
所以 Java 就搞出了 JDBC,约定一组 API 为 JDBC,里面包含一些类和方法, 通过这些类和方法实现数据库的基本操作,由各厂商提供各自的 “数据库驱动包” 来和 JDBC 的 API 对接。
所以,只要掌握这一套 JDBC API 就可以操作各种数据库了。
JDBC 为多种关系数据库提供了统一访问方式,作为特定厂商数据库访问API的一种高级抽象,它主要包含一些通用的接口类。
JDBC 优势:
注意:
JDBC 只支持关系型数据库, 不支持非关系型数据库。
创建一个项目即可。
// 创建数据源
DataSource dataSource = new MysqlDataSource();
((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=false");
((MysqlDataSource)dataSource).setUser("你的用户名");
((MysqlDataSource)dataSource).setPassword("你的数据库密码");
注意:
DataSource 对象描述了数据库对象在哪。
MySQL 数据连接的 URL 参数格式如下:
jdbc:mysql://服务器地址:端口/数据库名?参数名=参数值&参数名=参数值&…
服务器地址:我们写 的 127.0.0.1 是因为我们连接的是 本机的数据库, 所以用的是环回 IP 127.0.0.1,如果连接的是服务器上的数据库就得写对应的 IP 地址。
端口:MySQL 的默认端口号为 3306
数据库名:代码中的 URL 中的 test 要换为自己的数据库的名字。
setUser、setPassword 都是自己的用户名(MySQL 默认用户为 root )和密码。
为什么 使用向上转型,DataSource 引用 MysqlDataSource 对象,然后设置参数时 先强转(向下转型)回来,为什么不直接使用 MysqlDataSource 对象,这样不就不用来回转了嘛 ?
为了使代码低耦合:
后面代码中若需要用到 DataSource 类型,使用的相关参数也是 dataSource , 未来如果 不适用 MySQL 做数据库了, 使用其他数据库了 如 PostgreSQL 了,代码几乎不用怎么改动。
但是如果直接写成 :
MysqlDataSource mysqlDataSource = new MysqlDataSource();
这样不需要来回转换, 但是代码中充斥着 MysqlDataSource,到时候一旦更换数据库,代码要改动的地方就非常多了, 基本凉凉。
// 建立连接
Connection connection = dataSource.getConnection(); // 注意处理异常
JDBC 中构造的 sql 不需要带上 ; 符号
// 创建 sql
// 更新的 sql
String sql = "insert into student values ('wangwu', 90)";
PreparedStatement statement = connection.prepareStatement(sql);
// 查询的 sql
// String sql2 = "select * from student"; // 不用加上 ;
// PreparedStatement statement2 = connection.prepareStatement(sql2);
只一个 String 类型的 sql 还不行,需要把这个 String 包装成一个语句对象 PreparedStatement 。
// 执行 sql
int ret = statement.executeUpdate();
// 执行查询的 sql
// ResultSet resultSet = statement2.executeQuery();
执行 增删改 的 sql 使用 executeUpdate 方法, 返回值是受影响的行数。
执行 查询 的 sql 使用 executeQuery 方法,并使用 ResultSet 接收结果。
// 执行 查询的 sql 时需要遍历结果集
while (resultSet.next()) {
int age = resultSet.getInt("age");
String name = resultSet.getString("name");
System.out.println(" 姓名: " + name + " 年龄: " + age);
}
可以根据 列名 获取对应的值, 也可以根据列的下标(从 1 开始)获取,但是不推荐。
// resultSet.close(); // 如果查询的话需要释放
statement.close();
connection.close();
// 也要注意处理异常
先释放 statement 再 释放 connection
类似于关冰箱,先把抽屉关了, 再把冰箱门关了。
以查询为例:
public static void main(String[] args) throws SQLException {
// 1. 创建数据源
DataSource dataSource = new MysqlDataSource();
((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=false");
((MysqlDataSource)dataSource).setUser("root");
((MysqlDataSource)dataSource).setPassword("123456");
// 2. 建立数据库连接
Connection connection = dataSource.getConnection(); // 注意处理异常
// 3. 创建 sql
String sql = "select * from student"; // 不用加上 ;
PreparedStatement statement = connection.prepareStatement(sql);
// 4. 执行查询的 sql
ResultSet resultSet = statement.executeQuery();
// 5. 遍历结果集 (查询的话需要)
while (resultSet.next()) {
int age = resultSet.getInt("age");
String name = resultSet.getString("name");
System.out.println(" 姓名: " + name + " 年龄: " + age);
}
// 6. 释放连接
resultSet.close(); // 如果查询的话需要释放
statement.close();
connection.close();
}
使用步骤总结:
六个步骤:
注意:
整个写代码的时候注意处理异常,要么抛给上层调用者,要么自己处理掉。
使用 PreparedStatement 并使用占位符
String name = "zhouba";
int age = 88;
String sql = "insert into student values(?,?)"; // 不用加上 ;
PreparedStatement statement = connection.prepareStatement(sql);
statement.setString(1, name);
statement.setInt(2, age);
statement.executeUpdate();
使用 ? 先占一个位置,再使用 PreparedStatement 的 setXXX 方法进行替换,注意类型要一致。
注意该方法的第一个参数 是 ? 的位置, 下标从 1 开始,第二个参数是要填上去的值。
如果想一次插入多条数据, 就使用多个 ?, 对应替换上去就行了。
String sql = "insert into student values(?,?),(?,?),(?,?),(?,?)"; // 不用加上 ;
不要使用字符串拼接实现动态 sql, 因为会引入 sql 注入问题
比如: 可能我们如果使用 字符串拼接的话, 会像下面这么写
Scanner scanner = new Scanner(System.in);
String name = scanner.nextLine();
String password = scanner.nextLine();
String sql = "select * from user where name=" + name + " and password=" + password;
PreparedStatement statement = connection.prepareStatement(sql);
正常情况下没有什么问题, 但是, 有一个巨大的漏洞,
当用户输入:
'zhangsan'
'' or 1=1
(或者输入一些其他的恶意代码)
拼接成的 sql 为
select * from user where name='zhangsan' and password='' or 1=1
最后出现了一个 or 1=1
这在什么条件下都会成立的,所以说这个 sql 完全能执行成功,
在恶意用户不用知道 正确的用户名和密码的情况下,能查询数据库中的所有内容, 这是相当可怕的,尤其在一些银行等数据库内容非常机密的情况下。
所以, 我们不能使用 字符串拼接来实现动态的 sql ,
而 使用 PreparedStatement 的占位符则不会出现这种情况。
Connection 接口实现类由数据库提供,获取 Connection 对象通常有两种方式:
// 加载JDBC驱动程序:反射,这样调用初始化com.mysql.jdbc.Driver类,即将该类加载到JVM方法区,并执行该类的静态方法块、静态属性。
Class.forName("com.mysql.jdbc.Driver");
// 创建数据库连接
Connection connection = DriverManager.getConnection(url,user,password);
DataSource ds = new MysqlDataSource();
((MysqlDataSource) ds).setUrl("jdbc:mysql://localhost:3306/test");
((MysqlDataSource) ds).setUser("root");
((MysqlDataSource) ds).setPassword("123456");
Connection connection = ds.getConnection();
以上两种方式的区别是:
非常不建议使用 DriverManager :
Statement 对象主要是将SQL语句发送到数据库中。JDBC API 中主要提供了三种 Statement 对象。
实际开发中最常用的是 PreparedStatement 对象:
PreparedStatement 与 Statement 的区别:
好啦,以上就是对 JDBC 编程的讲解,希望能帮到你 !
评论区欢迎指正 !