什么是JDBC?
Java数据库连接(Java Database Connectivity,简称JDBC)是Java提供的一种API,允许Java应用程序与各种数据库进行交互。JDBC提供了一组标准的接口,开发者可以利用这些接口执行QL语句、处理结果集以及管理数据库连接。通过JDBC,Java应用程序能够轻松地进行增删改查操作(CRUD),使得数据库操作变得简单而高效。
下载JDBC驱动
MySL :: Download Connector/J
以MyQL为例
下载对应压缩包
找到合适的路径进行解压,解压后找到如下的 jar 包
IDEA引入驱动
1.新建一个项目,在项目下新建一个 lib 文件夹,将找到的 jar 包 复制进去
2.放进去jar包之后,右键lib,选择 add as library
3.找到下面的文件打开
4.复制内容,用于进行注册
Class.forName("com.myql.cj.jdbc.Driver");
下面先看一个例子
package com.ffyc;
import java.ql.Connection;
import java.ql.DriverManager;
import java.ql.SLException;
import java.ql.Statement;
public class jdbctest {
public static void main(String[] args) {
final String USERNAME="root";
final String PASSWORD = "123456";
final String URL =
"jdbc:myql://localhost:3306/kingdom_db?useSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai";
Connection conn = null;
Statement statement = null;
try {
//注册驱动
Class.forName("com.myql.cj.jdbc.Driver");
//获取连接
conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
//创建statement对象
statement = conn.createStatement();
String ql = "INSERT INTO dept_tab VALUES (6, '教学部', '102');";
//执行ql语句
statement.executeUpdate(ql);
System.out.println("数据插入成功!");
} catch (Exception e) {
throw new RuntimeException(e);
}finally {
//关闭资源
try {
if (statement != null) statement.close();
if (conn != null) conn.close();
} catch (SLException e) {
throw new RuntimeException(e);
}
}
}
}
s
URL的构成部分
jdbc:myql:
jdbc是Java数据库连接的协议前缀,指明这是一个JDBC类型的连接。
myql表示使用MySL数据库。
localhost:
localhost指的是数据库服务器的地址。在这里,它表示数据库安装在本地计算机上。如果您要连接远程数据库,可以替换为相应的IP地址或主机名。
:3306:
3306是MyS默认的端口号。它告诉JDBC在这个端口与MySL数据库进行连接。如果您的MySL数据库使用了不同的端口,请相应地更改此值。
/kingdom_db:
/kingdom_db是您要连接的数据库的名称。在这个例子中,试图连接名为kingdom_db的数据库。
?useSSL=true:
?用于开始查询参数。这部分包含了一些用于配置连接行为的选项。
useSSL=true指示JDBC驱动程序在连接时使用SSL加密。这对于保护数据传输是一个安全措施。
&useUnicode=true:
&用于分隔多个查询参数。
useUnicode=true表示使用Unicode字符编码,确保对于包含多语言字符的数据能够正确地处理和存储。
&characterEncoding=utf-8:
characterEncoding=utf-8指定了字符编码为UTF-8。UTF-8是一种广泛使用的字符编码方式,它支持多种语言字符的表示。这样可以避免字符乱码问题。
&serverTimezone=Asia/Shanghai:
serverTimezone=Asia/Shanghai设置了数据库服务器时区。此参数对于处理日期和时间数据是很重要的,确保在进行时区转换时能够准确。
只需要修改一下 2 3 4的写法,其他基本都是固定写法,用的时候上网搜一下即可,不需要记住 。
这个URL提供了与MySL数据库连接所需的详细信息,包括服务器位置、端口号、数据库名称以及一系列连接参数。正确地配置这些参数有助于确保您的应用程序能够稳定、高效地与数据库交互,同时提高安全性和数据的一致性。
JDBC中的常用方法及解释
注册驱动: Class.forName("com.mysl.cj.jdbc.Driver"); 这行代码用于加载MySL的JDBC驱动,在使用JDBC时必须先注册相应的数据库驱动。
获取连接: Connection conn = DriverManager.getConnection(URL, USERNAME, PASSWORD); 通过DriverManager获取到数据库的连接,这样才能进行后续的QL操作。
创建预编译语句: PreparedStatement pst = conn.prepareStatement(sl); 预编译语句主要用于执行QL语句,其具有参数占位符,使得插入的值更安全, 可防止SL注入击。
执行更新或查询: pst.executeUpdate(); 和 ResultSet rs = pst.executeQuery(); 这两个方法用于执行SL语句,前者用于执行更新(如插入、删除、更新),后者用于查询并返回结果集。
关闭连接: 在操作完成后应及时关闭连接,以释放资源。
PreparedStatement vs. Statement
Statement
使用Statement时,SL语句及参数是拼接在一起的,这意味着开发者需要手动构建整个SL字符串。
Statement在执行前不会进行预编译,因此每次执行SL时都会重新解析并编译SL语句,这会影响性能。
示例代码:
String username = "user";
String password = "pass123";
String ql = "SELECT * FROM user_tab WHERE username = '" + username + "' AND user_password = '" + password + "'";
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sl);
PreparedStatement
PreparedStatement使用占位符(?)来表示参数,QL语句是通过预编译的,这可以有效提升性能,减少数据库的负担。
PreparedStatement可以防止SL注入,因为参数是在执行时传递给SL的,JDBC会自动进行转义处理。
示例代码:
String sl = "SELECT * FROM user_tab WHERE username = ? AND user_password = ?";
PreparedStatement pst = conn.prepareStatement(sl);
pst.setString(1, username); // 设置第一个参数
pst.setString(2, password); // 设置第二个参数
ResultSet rs = pst.executeQuery();
SL注入漏
SL注入是一种常见的安全击手段,攻者可以通过在输入字段中插入恶SL代码来操纵数据库。例如,在使用Statement的情况下,以下拼接 SL 的方式就容易受到SL注入攻:
String unsafeUsername = "' OR '1'='1"; // 击者输入的用户名
String sl = "SELECT * FROM user_tab WHERE username = '" + unsafeUsername + "'";
ResultSet rs = stmt.executeQuery(sl);
在这个例子中,如果unsafeUsername被设置为' OR '1'='1,那么QL语句实际上变成了:
SELECT * FROM user_tab WHERE username = '' OR '1'='1'
这个查询会返回user_tab表中的所有用户,因为OR '1'='1'始终为真。
相比之下,使用PreparedStatement可以有效防止这样的击。例如:
String sl = "SELECT * FROM user_tab WHERE username = ? AND user_password = ?";
PreparedStatement pst = conn.prepareStatement(sq);
pst.setString(1, unsafeUsername); // 输入的用户名
pst.setString(2, password);
ResultSet rs = pst.executeQuery();
在这种情况下,unsafeUsername的值不会被直接当作SL代码执行,而是只作为参数处理。因此,即使击者输入了恶的SL片段,也不会改变原有QL的结构,防止了QL注入的发生。
这就是为什么要用PreparedStatement而不用Statement
简单封装
由于每次连接数据库都有一些重复的代码要写,所以我们对它进行简单的封装,下面的例子展示了如何封装JDBC操作,以便于日后的使用:
JdbcUtil 类
package com.util;
import java.ql.*;
/**
* static
*/
public class JdbcUtil {
static final String USERNAME = "root";
static final String PASSWORD = "123456";
static final String URL =
"jdbc:mysl://localhost:3306/kingdom_db?useSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai";
static Connection conn;
static PreparedStatement pst;
static ResultSet rs;
static{
registry();
}
/**
* 注册驱动
*/
private static void registry(){
try {
Class.forName("com.myl.cj.jdbc.Driver");
}catch (Exception e){
e.printStackTrace();
}
}
public static void connect(){
try {
conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
} catch (SLException e) {
throw new RuntimeException(e);
}
}
/**
* 预编译ql语句
*/
public static void prepareStatement(String sl,Object ... vals){
try {
pst = conn.prepareStatement(ql);
for(int i=0;i<vals.length;i++){
pst.setObject(i+1, vals[i]);
}
} catch (QLException e) {
throw new RuntimeException(e);
}
}
/**
* 增删改sl语句
*/
public static void executeUpdate(){
try {
pst.executeUpdate();
} catch (SLException e) {
throw new RuntimeException(e);
}
}
/**
* 查询ql语句
*/
public static ResultSet executeQuery(){
try {
rs = pst.executeQuery();
} catch (SLException e) {
throw new RuntimeException(e);
}
return rs;
}
public static void close(){
try {
if(rs!=null) rs.close();
if(pst!=null) pst.close();
if(conn!=null) conn.close();
} catch (SLException e) {
throw new RuntimeException(e);
}
}
}
DeptDemo类
package com.ffyc;
import com.util.JdbcUtil;
import java.sl.ResultSet;
import java.sq.SLException;
import java.util.Scanner;
public class DeptDemo {
public static void main(String[] args) throws SLException {
JdbcUtil.connect();
String sl = null;
ResultSet rs= null;
Scanner sc = new Scanner(System.in);
System.out.println("1. 添加部门信息\t2.查询所有部门信息");
System.out.println("3. 根据部门名称查询");
System.out.print("请选择: ");
String choice = sc.nextLine();
switch (choice) {
case "1":
System.out.print("请输入部门名称: ");
String name = sc.nextLine();
System.out.print("请输入部门位置: ");
String loc = sc.nextLine();
sl = "INSERT INTO dept_tab(dept_name, dept_loc) VALUES(?,?)";
JdbcUtil.prepareStatement(sq, name,loc);
JdbcUtil.executeUpdate();
System.out.println("添加成功");
break;
case "2":
sl = "SELECT * FROM dept_tab";
JdbcUtil.prepareStatement(sl );
rs = JdbcUtil.executeQuery();
while(rs.next()){
System.out.print(rs.getObject("dept_id"));
System.out.print("-"+rs.getObject("dept_name"));
System.out.print("-"+rs.getObject("dept_loc"));
System.out.println();
}
break;
case "3":
System.out.print("请输入部门的名称: ");
String nName= sc.nextLine();
sl = "SELECT * FROM dept_tab WHERE dept_name LIKE ?";
JdbcUtil.prepareStatement(sl,"%"+nName+"%");
rs = JdbcUtil.executeQuery();
while(rs.next()){
System.out.print(rs.getObject("dept_id"));
System.out.print("-"+rs.getObject("dept_name"));
System.out.print("-"+rs.getObject("dept_loc"));
System.out.println();
}
break;
default:
System.out.println("输入不合法..");
}
JdbcUtil.close();
}
}
代码解释
以上面这个例子。我对必要的地方做出解释说明
1.数据库连接
String sq = "INSERT INTO dept_tab(dept_name, dept_loc) VALUES(?,?)";
JdbcUtil.prepareStatement(sl, name, loc);
JdbcUtil.executeUpdate();
JdbcUtil.connect();
通过 JdbcUtil 类的 connect 方法连接到数据库。
2.用户交互
Scanner sc = new Scanner(System.in);
System.out.println("1. 添加部门信息\t2.查询所有部门信息");
System.out.println("3. 根据部门名称查询");
使用 Scanner 类从控制台获取用户输入,提示用户选择要执行的操作。
3.添加部门信息
String sl = "INSERT INTO dept_tab(dept_name, dept_loc) VALUES(?,?)";
JdbcUtil.prepareStatement(sl, name, loc);
JdbcUtil.executeUpdate();
重点是要对JdbcUtil这个封装类的方法理解,这是我们自定以的封装类
JDBC的优缺点
优点
平台独立性:作为 Java 的一部分,JDBC 具有平台无关性,可以在任何支持 Java 的环境中运行。
标准化接口:JDBC 提供了统一的 API,使得不同数据库之间的操作变得一致。
灵活性:支持多种数据库,如 MySL、Oracle、PostgreSL 等,只需更换驱动程序即可。
缺点
性能开销:传统的 JDBC 连接可能存在性能问题,尤其是在大量数据操作时。
代码复杂性:直接使用 JDBC 需要编写较多的样板代码,增加了开发的复杂性。
异常处理:JDBC 的异常处理相对复杂,开发者需要处理多种异常类型。
总结
JDBC 是 Java 开发中必不可少的组成部分,它为开发者提供了一种灵活、标准化的方法与数据库交互。尽管存在一些缺点,但通过合理的设计和封装,可以最大限度地发挥 JDBC 的优势。作为 Java 开发者,理解 JDBC 的工作原理及操作方式,将对提升数据库管理能力大有裨益。
标签:JDBC,Java,String,rs,数据库,System,dept From: https://blog.51cto.com/u_16955150/12387385