JDBC

it2025-05-26  23

JDBC

JDBC的概念:

客户端操作MYSQL数据库的方式

使用DOS命令行方式使用第三方客户端来访问MySQL:SQLyog、Navicat、SQLWave、MyDB Studio、EMS SQL Manager for MySQL通过Java来访问MySQL数据库

JDBC的作用

通过JDBC可以让Java操作数据库

JDBC会用到的包

java.sql:JDBC访问数据库的基础包,如:java.sql.Connectionjavax.sql: JDBC访问数据库的扩展包数据库的驱动,各大数据库厂商来实现。如:MySQL的驱动:com.mysql.jdbc.Driver

JDBC四个核心对象

DriverManager:注册驱动

Connection:Java程序和数据库之间的连接(桥梁)

Statement:执行SQL语句的对象(敞篷车,SQL注入问题,弃用)

PreparedStatement:执行SQL语句的对象(安全,推荐)

ResultSet:结果集,保存查询到的数据(用循环逐行调用 rs.next() )

运用Statement方式进行数据库操作

JDBC实现对单表数据增、删、改

准备数据:

-- 创建分类表 CREATE TABLE category ( cid INT PRIMARY KEY AUTO_INCREMENT, cname VARCHAR(100) ); -- 初始化数据 INSERT INTO category (cname) VALUES('家电'); INSERT INTO category (cname) VALUES('服饰'); INSERT INTO category (cname) VALUES('化妆品');

API介绍

获取Statement对象

在java.sql.Connection接口中有如下方法获取到Statement对象

Statement createStatement() 创建一个 Statement 对象来将 SQL 语句发送到数据库

Statement的API介绍

boolean execute(String sql) 用执行任何SQL语句,如果是查询返回true,如果不是查询语句返回false; 通常不用 int executeUpdate(String sql) 用于执行增删改等语句; 返回影响的行数 ResultSet executeQuery(String sql) 用于执行查询语句; 返回查询到的结果集

executeQuery:用于执行查询SQL

executeUpdate:用于执行除查询外的SQL

public class Demo03 { public static void main(String[] args) throws Exception { //反射方式进行注册 ​ Class.forName("com.mysql.jdbc.Driver"); //创建连接,变量分别为:IP地址、端口号、数据库名,数据库账号,密码 Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/yyc", "root", "root"); System.out.println(conn); // 从连接中拿到一个Statement对象 Statement stmt = conn.createStatement(); // 1.插入记录,sql语句最后要加;号,不然GG String sql = "INSERT INTO category (cname) VALUES ('手机');"; int i = stmt.executeUpdate(sql); System.out.println("影响的行数:" + i); // 2.修改记录 sql = "UPDATE category SET cname='汽车' WHERE cid=4;"; i = stmt.executeUpdate(sql); System.out.println("影响的行数:" + i); // 3.删除记录 sql = "DELETE FROM category WHERE cid=1;"; i = stmt.executeUpdate(sql); System.out.println("影响的行数:" + i); // 释放资源 stmt.close(); conn.close(); }

}

JDBC用Statement实现对单表数据查询

注册驱动获取连接获取到Statement使用Statement执行SQLResultSet处理结果关闭资源 public class Demo04 { public static void main(String[] args) throws Exception { Class.forName("com.mysql.jdbc.Driver"); Connection conn = DriverManager.getConnection("jdbc:mysql:///yyc", "root", "root"); Statement stmt = conn.createStatement(); String sql = "SELECT * FROM category;"; ResultSet rs = stmt.executeQuery(sql); // 内部有一个指针,只能取指针指向的那条记录 while (rs.next()) { // 指针移动一行,有数据才返回true // 取出数据 int cid = rs.getInt("cid"); String cname = rs.getString("cname"); System.out.println(cid + " == " + cname); } // 关闭资源 rs.close(); stmt.close(); conn.close(); }

}

JDBC事务

事务的作用

让一串SQL完整执行,一处未成功执行全盘回滚;

准备数据

CREATE TABLE account ( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(10), balance DOUBLE ); -- 添加数据 INSERT INTO account (NAME, balance) VALUES ('张三', 1000), ('李四', 1000);

API介绍

Connection接口中与事务有关的方法

void setAutoCommit(boolean autoCommit) throws SQLException; false:开启事务, ture:关闭事务 void commit() throws SQLException; 提交事务 void rollback() throws SQLException; 回滚事务

使用步骤

注册驱动获取连接开启事务获取到Statement使用Statement执行SQL提交或回滚事务关闭资源 public class Demo05 { public static void main(String[] args) { Connection conn = null; try { // 拿到连接 Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection("jdbc:mysql:///yyc", "root", "root"); // 开启事务为true,关闭为false conn.setAutoCommit(false); Statement pstmt = conn.createStatement(); // 张三减500 String sql = "UPDATE account SET balance = balance - 500 WHERE id=1;"; pstmt.executeUpdate(sql); // 模拟异常 // int i = 10 / 0; // 李四加500 sql = "UPDATE account SET balance = balance + 500 WHERE id=2;"; pstmt.executeUpdate(sql); pstmt.close(); // 成功,提交事务 System.out.println("成功,提交事务"); conn.commit(); } catch (Exception e) { // 失败,回滚事务 try { System.out.println("出了异常,回滚事务"); conn.rollback(); } catch (SQLException e1) { e1.printStackTrace(); } } finally { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }

}

编写JDBC工具类

编写JDBC工具类步骤

将固定字符串定义为常量

在静态代码块中注册驱动

提供一个获取连接的方法static Connection getConneciton();

定义关闭资源的方法close(Connection conn, Statement stmt, ResultSet rs)

重载关闭方法close(Connection conn, Statement stmt)

`JDBCUtils.java` public class JDBCUtils { // 1.将固定字符串定义为常量 private static final String DRIVER_CLASS = "com.mysql.jdbc.Driver"; private static final String URL = "jdbc:mysql:///yyc"; private static final String USER = "root"; private static final String PASSWORD = "root"; // 2.在静态代码块中注册驱动(只注册一次) // 当这个类加载到内存的时候就走这个静态代码块,再去触发Driver类中的静态代码块,主动注册 static { try { Class.forName(DRIVER_CLASS); } catch (ClassNotFoundException e) {} } // 3.提供一个获取连接的方法static Connection getConneciton(); // 我们面向JDBC编程 public static Connection getConnection() throws SQLException { InputStream is = JDBCUtils.class.getResourceAsStream("/jdbc.properties"); Properties pp = new Properties(); pp.load(is); Connection conn = DriverManager.getConnection(URL, pp); return conn; } // 5.重载关闭方法close(Connection conn, Statement stmt) public static void close(Connection conn, Statement stmt) { close(conn, stmt, null); } // 4.定义关闭资源的方法close(Connection conn, Statement stmt, ResultSet rs) public static void close(Connection conn, Statement stmt, ResultSet rs) { if (rs != null) { try { rs.close(); } catch (SQLException e) {} } if (stmt != null) { try { stmt.close(); } catch (SQLException e) {} } if (conn != null) { try { conn.close(); } catch (SQLException e) {} } } }

SQL注入问题

请输入用户名: hehe 请输入密码: a' or '1'='1 // 代码中的SQL语句 "SELECT * FROM user WHERE name='" + name + "' AND password='" + password + "';"; // 将用户输入的账号密码拼接后 "SELECT * FROM user WHERE name='hehe' AND password='a' or '1'='1';"

让用户输入的密码和SQL语句进行字符串拼接。用户输入的内容作为了SQL语句语法的一部分,改变了原有SQL真正的意义,导致数据库访问出现安全问题

运用PreparedStatement方式进行数据库操作

PreparedStatement的API介绍

在java.sql.PreparedStatement中有设置SQL语句参数,和执行参数化的SQL语句的方法

void setDouble(int parameterIndex, double x) 将指定参数设置为给定 Java double 值。 void setFloat(int parameterIndex, float x) 将指定参数设置为给定 Java REAL 值。 void setInt(int parameterIndex, int x) 将指定参数设置为给定 Java int 值。 void setLong(int parameterIndex, long x) 将指定参数设置为给定 Java long 值。 void setObject(int parameterIndex, Object x) 使用给定对象设置指定参数的值。 void setString(int parameterIndex, String x) 将指定参数设置为给定 Java String 值。 ResultSet executeQuery() 在此 PreparedStatement 对象中执行 SQL 查询,并返回该查询生成的ResultSet对象。 int executeUpdate() 在此 PreparedStatement 对象中执行 SQL 语句,该语句必须是一个 SQL 数据操作语言DML语句,比如 INSERT、UPDATE 或 DELETE 语句;或者是无返回内容的 SQL 语句,比如 DDL 语句。

PreparedSatement使用步骤

获取连接编写SQL语句,未知内容使用?占位:"SELECT * FROM user WHERE name=? AND password=?;"; 参数化的SQL获得PreparedStatement对象设置实际参数执行参数化SQL语句关闭资源

PreparedStatement实现增删查改

创建表结构

CREATE TABLE employee ( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(20), age INT, address VARCHAR(50) );

添加数据

向Employee表添加3条记录

// 添加数据: 向Employee表添加3条记录 public static void addEmployee() throws Exception { Connection conn = JDBCUtils.getConnection(); String sql = "INSERT INTO employee VALUES (NULL, ?, ?, ?);"; // prepareStatement()会先将SQL语句发送给数据库预编译。 PreparedStatement pstmt = conn.prepareStatement(sql); // 设置参数 pstmt.setString(1, "刘德华"); pstmt.setInt(2, 57); pstmt.setString(3, "香港"); int i = pstmt.executeUpdate(); System.out.println("影响的行数:" + i); // 再次设置参数 pstmt.setString(1, "张学友"); pstmt.setInt(2, 55); pstmt.setString(3, "澳门"); i = pstmt.executeUpdate(); System.out.println("影响的行数:" + i); // 再次设置参数 pstmt.setString(1, "黎明"); pstmt.setInt(2, 52); pstmt.setString(3, "香港"); i = pstmt.executeUpdate(); System.out.println("影响的行数:" + i); JDBCUtils.close(conn, pstmt); }

PreparedStatement删除数据

删除id为2的员工

// 删除数据: 删除id为2的员工 public static void deleteEmployee() throws Exception { Connection conn = JDBCUtils.getConnection(); String sql = "DELETE FROM employee WHERE id=?;"; PreparedStatement pstmt = conn.prepareStatement(sql); pstmt.setInt(1, 2); int i = pstmt.executeUpdate(); System.out.println("影响的行数:" + i); JDBCUtils.close(conn, pstmt); }

PreparedSatement查询数据

实现步骤

定义Employee类得到连接对象得到PreparedStatement对象编写SQL语句并执行,保存ResultSet创建一个集合用于保存所有的员工对象每次循环将一条记录存放到一个员工对象中把员工对象放到集合中关闭资源遍历集合,循环输出员工对象

代码

public class Employee { private int id; private String name; private int age; private String address; public Employee() { } public Employee(int id, String name, int age, String address) { this.id = id; this.name = name; this.age = age; this.address = address; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "Employee2 [id=" + id + ", name=" + name + ", age=" + age + ", address=" + address + "]"; } } // 查询数据: 查询id小于8的员工信息,并保存到员工类中 public static void queryEmployee() throws Exception { Connection conn = JDBCUtils.getConnection(); String sql = "SELECT * FROM employee WHERE id<?;"; PreparedStatement pstmt = conn.prepareStatement(sql); pstmt.setInt(1, 26); ResultSet rs = pstmt.executeQuery(); // 创建集合存放多个Employee2对象 ArrayList<Employee> list = new ArrayList<>(); while (rs.next()) { // 移动到下一行有数据,取出这行数据 int id = rs.getInt("id"); String name = rs.getString("name"); int age = rs.getInt("age"); String address = rs.getString("address"); // 创建Employee2对象 Employee e = new Employee(id, name, age, address); // 将创建好的员工添加到集合中 list.add(e); } // 输出对象 for (Employee e : list) { System.out.println(e); } JDBCUtils.close(conn, pstmt, rs); }

ParameterMetaData元数据

什么是元数据

元数据其实就是定义表的字段

ParameterMetaData作用

ParameterMetaData可用于获取有关PreparedStatement对象中每个参数标记的类型和属性。

select * from user where name=? and password=? // ParameterMetaData可以用来获取?的个数和类型

ParameterMetaDataAPI介绍

int getParameterCount() 获取PreparedStatement的SQL语句参数?的个数 int getParameterType(int param) 获取指定参数的SQL类型。

使用步骤

获取ParameterMetaData对象使用对象调用方法

注意事项

不是所有的数据库驱动都能后去到参数类型(MySQL会出异常)

案例代码

public class Demo01 { public static void main(String[] args) throws Exception { Connection conn = DataSourceUtils.getConnection(); String sql = "INSERT INTO student (name, age, score) VALUES (?, ?, ?)"; PreparedStatement stmt = conn.prepareStatement(sql); ParameterMetaData md = stmt.getParameterMetaData(); System.out.println("参数个数: " + md.getParameterCount()); // Parameter metadata not available for the given statement // MySQL不支持获取参数类型 // System.out.println("参数类型: " + md.getParameterType(1)); } }

ResultSetMetaData元数据

ResultSetMetaData作用

ResultSetMetaData可用于获取有关ResultSet对象中列的类型和属性的信息。

如何获取ResultSetMetaData

通过ResultSet的getMetaData()方法来获取到ResultSetMetaData对象

ResultSetMetaDataAPI介绍

int getColumnCount() 返回此 ResultSet对象中的列数 String getColumnName(int column) 获取指定列的名称 String getColumnTypeName(int column) 获取指定列的数据库特定类型名称

使用步骤

获取ResultSetMetaData对象使用对象调用方法

案例代码

// ResultSetMetaData public static void test02() throws SQLException { Connection conn = DataSourceUtils.getConnection(); String sql = "SELECT * FROM student WHERE id=1"; PreparedStatement stmt = conn.prepareStatement(sql); ResultSet rs = stmt.executeQuery(); // 获取结果集元数据 ResultSetMetaData md = rs.getMetaData(); int num = md.getColumnCount(); System.out.println("列数:" + num); for (int i = 0; i < num; i++) { System.out.println("列名:" + md.getColumnName(i + 1)); // 获取列名 System.out.println("列类型:" + md.getColumnTypeName(i + 1)); // 获取类的类型 System.out.println("-----------"); } }

用方法

案例代码

// ResultSetMetaData public static void test02() throws SQLException { Connection conn = DataSourceUtils.getConnection(); String sql = "SELECT * FROM student WHERE id=1"; PreparedStatement stmt = conn.prepareStatement(sql); ResultSet rs = stmt.executeQuery(); // 获取结果集元数据 ResultSetMetaData md = rs.getMetaData(); int num = md.getColumnCount(); System.out.println("列数:" + num); for (int i = 0; i < num; i++) { System.out.println("列名:" + md.getColumnName(i + 1)); // 获取列名 System.out.println("列类型:" + md.getColumnTypeName(i + 1)); // 获取类的类型 System.out.println("-----------"); } }
最新回复(0)