JDBC API
获取数据库连接5种方式
- 通过new创建Driver对象;
- 使用反射加载Driver类,动态加载,减少依赖性,更加灵活;
- 使用DriverManager 替代 Driver 进行统一管理,有了更好的扩展性;
- 使用 Class.forName 自动完成注册驱动,简化代码;
- 在方式4的基础上改进,增加配置文件,让mysql连接更灵活,最推荐使用;
代码演示:
- package com.hspedu.jdbc;
- import com.mysql.jdbc.Driver;
- import org.junit.jupiter.api.Test;
- import java.io.FileInputStream;
- import java.io.FileNotFoundException;
- import java.io.IOException;
- import java.sql.Connection;
- import java.sql.DriverManager;
- import java.sql.SQLException;
- import java.util.Properties;
- /**
- * 分析java连接mysql的5种方式
- */
- public class JdbcConn {
- //方式1
- @Test
- public void connect01() throws SQLException {
- Driver driver = new Driver();
- String url = "jdbc:mysql://localhost:3306/jdbc_learning";
- Properties properties = new Properties();
- properties.setProperty("user", "root");//用户名
- properties.setProperty("password", "root");//密码
- Connection connection = driver.connect(url, properties);
- System.out.println("第一种方式" + connection);
- connection.close();
- }
- //方式2
- @Test
- public void connect02() throws ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException {
- //使用反射加载Driver类,动态加载,减少依赖性,更加灵活
- Class<?> aClass = Class.forName("com.mysql.jdbc.Driver");
- Driver driver = (Driver) aClass.newInstance();
- String url = "jdbc:mysql://localhost:3306/jdbc_learning";
- Properties properties = new Properties();
- properties.setProperty("user", "root");//用户名
- properties.setProperty("password", "root");//密码
- Connection connection = driver.connect(url, properties);
- System.out.println("第二种方式" + connection);
- connection.close();
- }
- //方式3 使用DriverManager 替代 Driver 进行统一管理,有了更好的扩展性
- @Test
- public void connect03() throws ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException {
- //使用反射加载Driver类
- Class<?> aClass = Class.forName("com.mysql.jdbc.Driver");
- Driver driver = (Driver) aClass.newInstance();
- String url = "jdbc:mysql://localhost:3306/jdbc_learning";
- String user = "root";
- String password = "root";
- DriverManager.registerDriver(driver);//注册Driver驱动,DriverManager是Java自带的类
- Connection connection = DriverManager.getConnection(url, user, password);
- System.out.println("第三种方式" + connection);
- }
- //方式4 使用 Class.forName 自动完成注册驱动,简化代码
- //这种方式推荐使用,使用最多
- @Test
- public void connect04() throws ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException {
- //使用反射加载Driver类
- //在加载 Driver类时,完成注册
- /*
- 源码:1. 静态代码块,在类加载时,会执行一次
- 2. 因此注册driver的工作在底层已经完成了
- static {
- try {
- DriverManager.registerDriver(new Driver());
- } catch (SQLException var1) {
- throw new RuntimeException("Can't register driver!");
- }
- }
- */
- //1.mysqL驱动5.1.6可以无需CLass.forName("com.mysql.jdbc.Driver");
- //2.从jdk1.5以后使用了jdbc4,不再需要显示调用class.forName()注册驱动而是自动调用驱动
- //jar包下META-INF\services\java.sql.Driver文本中的类名称去注册
- //3.建议还是写上CLass.forName("com.mysql.jdbc.Driver"),更加明确
- Class.forName("com.mysql.jdbc.Driver");//内部有一段静态代码会默认自动注册
- String url = "jdbc:mysql://localhost:3306/jdbc_learning";
- String user = "root";
- String password = "root";
- Connection connection = DriverManager.getConnection(url, user, password);
- System.out.println("第四种方式" + connection);
- }
- //方式5 在方式4的基础上改进,增加配置文件,让mysql连接更灵活,最推荐使用
- @Test
- public void connect05() throws IOException, ClassNotFoundException, SQLException {
- //通过Properties对象获取配置文件的信息
- Properties properties = new Properties();
- properties.load(new FileInputStream("src\\mysql.properties"));
- //获取相关的值
- String user = properties.getProperty("user");
- String password = properties.getProperty("password");
- String driver = properties.getProperty("driver");
- String url = properties.getProperty("url");
- Class.forName(driver);//建议写上
- Connection connection = DriverManager.getConnection(url, user, password);
- System.out.println("第五种方式" + connection);
- }
- }
复制代码 配置文件mysql.properties:
- user=root
- password=zyl
- url=jdbc:mysql://localhost:3306/jdbc_learning
- driver=com.mysql.jdbc.Driver
复制代码 ResultSet[结果集]
- 基本介绍
- 表示数据库结果集的数据表,通常通过执行查询数据库的语句生成;
- ResultSet对象保持一个光标指向其当前的数据行。最初,光标位于第一行前;
- next方法将光标移动到下一行,并且由于在ResultSet对象中没有更多行时返回false,因此可以在while循环中使用循环来遍历结果集。

- 代码演示:
- package com.hspedu.jdbc.resultset_;
- import java.io.FileInputStream;
- import java.io.FileNotFoundException;
- import java.io.IOException;
- import java.sql.*;
- import java.util.Properties;
- /**
- * @author: 86199
- * @date: 2023/6/14 21:52
- * Description: 演示select 语句 返回 ResultSet,并取出结果
- */
- @SuppressWarnings({"all"})
- public class ResultSet_ {
- public static void main(String[] args) throws IOException, ClassNotFoundException, SQLException {
- //通过Properties对象获取配置文件的信息
- Properties properties = new Properties();
- properties.load(new FileInputStream("src\\mysql.properties"));
- //获取相关的值
- String user = properties.getProperty("user");
- String password = properties.getProperty("password");
- String driver = properties.getProperty("driver");
- String url = properties.getProperty("url");
- //1. 注册驱动
- Class.forName(driver);//建议写上
- //2. 得到连接
- Connection connection = DriverManager.getConnection(url, user, password);
- //3. 得到Statement
- Statement statement = connection.createStatement();
- //组织sql语句
- String sql = "select id, name, sex, borndate from actor;";
- /*
- 1 周星驰 男 1970-11-11 00:00:00 110
- 2 刘德华 男 1970-11-11 00:00:00 110
- 3 刘德华 男 1970-11-11 00:00:00 110
- */
- //执行给定的SQL语句,该语句返回单个ResultSet对象
- /*
- 源码:
- */
- ResultSet resultSet = statement.executeQuery(sql);
- while (resultSet.next()) {//让光标后移,如果没有更多行,则返回false
- int id = resultSet.getInt(1);//获取该行的第1列
- String name = resultSet.getString(2);//获取该行的第2列
- String sex = resultSet.getString(3);
- String date = resultSet.getString(4);
- System.out.println(id + "\t" + name + "\t" + sex + "\t" + date);
- }
- //关闭资源
- resultSet.close();
- statement.close();
- connection.close();
- }
- }
复制代码
-
-
- ## Statement对象
- - **基本介绍**
- 1. Statement对象,用于执行静态SQL语句并返回其生成的结果的对象。
- 2. 在连接建立之后,需要对数据库进行访问,执行命名或是SQL语句,可以通过
- - Statement [存在SQL注入]
- - ==PreparedStatement==(预处理)
- - CallableStatement(存储过程)
- 3. Statement对象执行SQL语句存在==SQL注入==的风险
- - **SQL注入**是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的SQL语句段或命令,恶意攻击数据库。
- - 要防范 SQL注入,只要用 **PreparedStatement**(从Statement扩展而来)取代 Statement 就可以了。
- **MySQL代码:**
- ```mysql
- -- 演示sql注入
- -- 创建一张表
- CREATE TABLE admin ( -- 管理员表
- `name` VARCHAR(32) NOT NULL UNIQUE,
- pwd VARCHAR(32) NOT NULL DEFAULT '') CHARACTER SET utf8;
- -- 添加数据
- INSERT INTO admin VALUES('jac', '123');
- -- 查找某个管理员是否存在
- SELECT *
- FROM admin
- WHERE `name` = 'tom' AND pwd = '123';
- -- SQL注入
- -- 输入用户名 1' or
- -- 输入密码 为 or '1' = '1
- -- SELECT *
- -- FROM admin
- -- WHERE `name` = '' AND pwd = '';
- SELECT *
- FROM admin
- WHERE `name` = '1' or' AND pwd = 'or '1' = '1';
复制代码 Java代码:
- package com.hspedu.jdbc.statement_;
- import java.io.FileInputStream;
- import java.io.FileNotFoundException;
- import java.io.IOException;
- import java.sql.*;
- import java.util.Properties;
- import java.util.Scanner;
- /**
- * @author: 86199
- * @date: 2023/6/15 22:24
- * Description: 演示 SQL注入的问题
- */
- public class Statement_ {
- public static void main(String[] args) throws IOException, ClassNotFoundException, SQLException {
- Scanner scanner = new Scanner(System.in);
- //让用户输入管理员用户名和密码
- System.out.print("请输入管理员名字:");
- String admin_name = scanner.nextLine();
- System.out.print("请输入管理员密码:");
- String admin_pwd = scanner.nextLine();
- //通过Properties对象获取配置文件的信息
- Properties properties = new Properties();
- properties.load(new FileInputStream("src\\mysql.properties"));
- //获取相关的值
- String user = properties.getProperty("user");
- String password = properties.getProperty("password");
- String driver = properties.getProperty("driver");
- String url = properties.getProperty("url");
- //1. 注册驱动
- Class.forName(driver);//建议写上
- //2. 得到连接
- Connection connection = DriverManager.getConnection(url, user, password);
- //3. 得到Statement
- Statement statement = connection.createStatement();
- //组织sql语句
- String sql = "SELECT name, pwd FROM admin where name = '"
- + admin_name + "' and pwd = '" + admin_pwd + "';";
- ResultSet resultSet = statement.executeQuery(sql);
- if (resultSet.next()) {//如果查询到一条记录,说明该管理员存在
- System.out.println("恭喜,登录成功");
- }else{
- System.out.println("对不起,登录失败");
- }
- resultSet.close();
- statement.close();
- connection.close();
- }
- }
- //运行
- /*
- 请输入管理员名字:1' or
- 请输入管理员密码:or '1' = '1
- 恭喜,登录成功
- */
复制代码 预处理(查询和修改)
- PreparedStatement 执行的SQL语句中的参数用问号(?)来表示,调用 PreparedStatement 对象的 setXxx() 方法来设置这些参数。setXxx() 方法有两个参数,第一个参数都是int,要设置SQL语句中的参数的索引(从 1 开始),第二个是设置的 SQL 语句中的参数的值。
- 调用 executeQuery(),返回 ResultSet 对象。
- 调用 executeUpdate():执行更新,包括增,删,修改
- package com.hspedu.jdbc.preparedstatement_;
- import java.io.FileInputStream;
- import java.io.FileNotFoundException;
- import java.io.IOException;
- import java.sql.*;
- import java.util.Properties;
- import java.util.Scanner;
- /**
- * @author: 86199
- * @date: 2023/7/17 20:43
- * Description: 演示PreparedStatement使用
- */
- public class PreparedStatement_ {
- public static void main(String[] args) throws IOException, ClassNotFoundException, SQLException {
- Scanner scanner = new Scanner(System.in);
- //让用户输入管理员用户名和密码
- System.out.print("请输入管理员名字:");
- String admin_name = scanner.nextLine();
- System.out.print("请输入管理员密码:");
- String admin_pwd = scanner.nextLine();
- //通过Properties对象获取配置文件的信息
- Properties properties = new Properties();
- properties.load(new FileInputStream("src\\mysql.properties"));
- //获取相关的值
- String user = properties.getProperty("user");
- String password = properties.getProperty("password");
- String driver = properties.getProperty("driver");
- String url = properties.getProperty("url");
- //1. 注册驱动
- Class.forName(driver);//建议写上
- //2. 得到连接
- Connection connection = DriverManager.getConnection(url, user, password);
- //sql中的?就相当于占位符
- String sql = "SELECT name, pwd FROM admin where name = ? and pwd = ? ;";
- //3. 得到PreparedStatement,这里的statement是实现了PreparedStatement接口的实现类的对象
- PreparedStatement statement = connection.prepareStatement(sql);
- //给 ? 赋值
- statement.setString(1, admin_name);
- statement.setString(2, admin_pwd);
- //执行sql语句,如果执行的是dml语句要用executeUpdate()
- ResultSet resultSet = statement.executeQuery();//()中不能再写sql语句,不然执行的就是带?的,填了sql语句就是调用了父类Statement的方法了
- if (resultSet.next()) {//如果查询到一条记录,说明该管理员存在
- System.out.println("恭喜,登录成功");
- }else{
- System.out.println("对不起,登录失败");
- }
- //关闭链接
- resultSet.close();
- statement.close();
- connection.close();
- }
- }
- //运行
- /*
- 请输入管理员名字:1' or
- 请输入管理员密码:or '1' = '1
- 对不起,登录失败
- */
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |