用天地图做网站,网址大全2345视频,网站怎么做uc整合,用asp.net做网站计数器找往期文章包括但不限于本期文章中不懂的知识点#xff1a; 个人主页#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏#xff1a; MYSQL 目录
JDBC的概念
JDBC的使用
加载驱动包
建立连接
创建 statement 对象
定义并执行SQL语句
处理结果集
关闭资源
SQL注入 …找往期文章包括但不限于本期文章中不懂的知识点 个人主页我要学编程(ಥ_ಥ)-CSDN博客 所属专栏 MYSQL 目录
JDBC的概念
JDBC的使用
加载驱动包
建立连接
创建 statement 对象
定义并执行SQL语句
处理结果集
关闭资源
SQL注入
优化后的JDBC
JDBC编程的两种方式对比 前面我们学习了MySQL数据库中SQL语句的基础语法并且在命令行上面也进行了一些实际的操作。现在我们就来学习使用IDEA去编写SQL语句来操作数据库。
JDBC的概念
JDBCJava DataBase ConnectivityJava数据库连接是Java程序和数据库之间的桥梁包含 了一套Java定义的用于执行SQL语句的接口使开发者能够编写数据库的程序。JDBC的主要作用是与数据库建立连接、发送SQL语句和处理数据库执行结果。关系示意图 从上面我们知道了JDBC其实就是一套Java源生的。而其的实现也与我们无关是由数据库厂商自己提供的。我们只需要去使用即可。
接下来我们就来使用JDBC去操作数据库。
JDBC的使用
JDBC的使用可以大致概括为以下几个方面
1、加载数据库厂商提供的驱动包。即实现了JDBC的接口
2、建立数据库连接
3、创建statement对象
4、编写SQL语句并通过statement对象去执行SQL语句
5、接收结果集或者返回值
6、关闭资源 加载驱动包
加载驱动包的过程可以简单理解为在手机上安装一个软件的过程。 而安装软件的过程如下所示
1、打开应用商店
2、去应用商店里面找到该软件
3、下载该软件。
4、安装该软件在运行即可。
同理加载驱动包也是三个步骤
1、打开Maven官网驱动包全部在里面
Maven官网点我
2、找到与自己电脑中数据库版本相对应数据库 那问题来了怎么判断自己是哪个版本呢
按 win R 打开命令行然后输入 mysql -uroot -p接着摁下回车键再输入密码成功打开MySQL之后就输入 select version(); 去查询此时正在运行的MySQL的版本是多少。 如果你和我一样是MySQL8.0.39的话那么就是去第一个结果中找到MySQL8.3即可。 3、在该目录下来到Maven所在目录点击框内英文即可。 4、将复制的内容粘贴到Maven工程中。
这里首先得创建一个Maven工程。 然后只需要套个框架在框架内粘贴我们复制的内容即可。 接下来就是正式的加载驱动包了正如运行程序。 现在就已经将驱动包加载完成啦下面就是要建立连接了。
建立连接
// 2. 获取数据库连接
Connection connection DriverManager.getConnection(jdbc:mysql://127.0.0.1:3306/java?characterEncodingutf8 allowPublicKeyRetrievaltrueuseSSLfalse, root, 123456);;
这里是固定写法 即修改 3306/ 后面的值即对应的数据库。root 就是用户名123456 就是mysql的密码。
创建 statement 对象
// 3. 创建Statement对象
Statement statement connection.createStatement();
定义并执行SQL语句
// 4. 定义SQL并执行SQL语句
System.out.print(请输入学生姓名);
Scanner scanner new Scanner(System.in);
// 接收用户的输入
String name scanner.next();
// 把查询的列详细写出来
String sql select id, name, age, gender from student where name name ;
// 5. 执行SQL获取查询结果
resultSet statement.executeQuery(sql);
处理结果集
// 6. 对结果集进行遍历获取数据
// 如果一下条有记录返回true,没有则返回false
while (resultSet.next()) {// 获取学生的信息long stuId resultSet.getLong(1); // 这里的1是指第一列String stuName resultSet.getString(2);int stuAge resultSet.getInt(3);byte stuGender resultSet.getByte(4);System.out.println(MessageFormat.format(学生编号{0}, 学生姓名{1}, 学生年龄{2}, 学生性别{3},stuId, stuName, stuAge, stuGender));
}
关闭资源
// 依次释放资源关闭连接
if (resultSet ! null) {try {resultSet.close();} catch (SQLException e) {e.printStackTrace();}}
if (statement ! null) {try {statement.close();} catch (SQLException e) {e.printStackTrace();}
}
if (connection ! null) {try {connection.close();} catch (SQLException e) {e.printStackTrace();}
}
下面是综合的代码包括捕获异常
import java.sql.*;
import java.text.MessageFormat;
import java.util.Scanner;public class JDBC_Demo1 {public static void main(String[] args) {Connection connection null;Statement statement null;ResultSet resultSet null;try {// 1. 加载数据库厂商提供的驱动Class.forName(com.mysql.cj.jdbc.Driver);// 2. 获取数据库连接connection DriverManager.getConnection(jdbc:mysql://127.0.0.1:3306/java?characterEncodingutf8 allowPublicKeyRetrievaltrueuseSSLfalse, root, 123456);// 3. 创建Statement对象statement connection.createStatement();// 4. 定义SQL并执行SQL语句System.out.print(请输入学生姓名);Scanner scanner new Scanner(System.in);// 接收用户的输入String name scanner.next();String sql select id, name, age, gender from student where name name ;// 5. 执行SQL获取查询结果resultSet statement.executeQuery(sql);// 6. 对结果集进行遍历获取数据// 如果一下条有记录返回true,没有则返回falsewhile (resultSet.next()) {// 获取学生的信息long stuId resultSet.getLong(1);String stuName resultSet.getString(2);int stuAge resultSet.getInt(3);byte stuGender resultSet.getByte(4);System.out.println(MessageFormat.format(学生编号{0}, 学生姓名{1}, 学生年龄{2}, 学生性别{3},stuId, stuName, stuAge, stuGender));}} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();} finally {// 依次释放资源关闭连接if (resultSet ! null) {try {resultSet.close();} catch (SQLException e) {e.printStackTrace();}}if (statement ! null) {try {statement.close();} catch (SQLException e) {e.printStackTrace();}}if (connection ! null) {try {connection.close();} catch (SQLException e) {e.printStackTrace();}}}}
}注意try块 中定义的变量其作用域只是在try块中只有在全局的变量才能在try-catch 中使用并且在finally块中也是可以使用。全局只是相对try-catch和finally而言的
效果演示
JDBC 命令行 上面这种方法虽然的确可以操作数据库但是从性能来讲还是比较差的。因为DriverManager每次调用getConnection方法都会初始化一个新的连接使用完成后会关闭真实连接导致资源浪费。因此 DataSource就闪亮登场了。DataSource使用了连接池的技术会在初始化时创建一定数量的数据库连接这些连接可以重复使用关闭时并不是真正关闭连接而是将连接归还给连接池以供后续使用有效地提高资源利用率和和性能。
SQL注入
Statement 用于执行静态SQL语句并返回执行结果由于只能执行静态语句所以这里会有一个问题假设一个语句中需要动态的参数比如where子句中的条件那么只能通过字符串拼接的方式组装完成的SQL语句。就和我们上面写的一样但如果此时有人写了一个必然成立的代码呢 JDBC进行的检查就是将输入的SQL语句中的所有空格给去掉从而进行语法检查。 上面这种情况叫做 SQL注入。
字符串拼接形式构造SQL语句时如果不处理参数中的特殊字符就会造成SQL注入这是一个非常 严重的安全性问题。别人可以通过这种手段把数据内容全部盗取从而对公司、个人造成损失。
SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严攻击者可以在web应 用程序中事先定义好的查询语句的结尾上添加额外的SQL语句在管理员不知情的情况下实现非法操作以此来实现欺骗数据库服务器执行非授权的任意查询从而进一步得到相应的数据信息。
既然出现了这么严重的问题肯定是需要解决的因此便有了和编译代码的过程一样进行预编译。在预编译阶段处理SQL注入的问题。
预编译SQL语句对象SQL语句被预编译并存储在PreparedStatement对象中可以使用该对象多次执行SQL语句同时可以解决SQL注入问题。
优化后的JDBC
现在我们来写优化后的代码
import com.mysql.cj.jdbc.MysqlDataSource;import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.MessageFormat;
import java.util.Scanner;public class JDBC_Demo2 {public static void main(String[] args) {// 定义mysql数据源对象MysqlDataSource mysqlDataSource new MysqlDataSource();// 设置数据连接串// urlmysqlDataSource.setURL(jdbc:mysql://127.0.0.1:3306/java?characterEncodingutf8 allowPublicKeyRetrievaltrueuseSSLfalse);// 用户名mysqlDataSource.setUser(root);// 密码mysqlDataSource.setPassword(123456);Connection connection null;PreparedStatement preparedStatement null;ResultSet resultSet null;// 上面是厂商给我们提供的实现类我们要使用Java层面的数据源接口DataSource dataSource mysqlDataSource; // 向上转型try {// 从数据源中获取连接connection dataSource.getConnection();// 定义执行的SQLString sql select id, name, age, gender from student where name ?; // 使用占位符// 对SQL语句进行预编译preparedStatement connection.prepareStatement(sql);// 接收输入数据System.out.print(请输入学生姓名);Scanner scanner new Scanner(System.in);String name scanner.next();// 用真实数据代替占位符preparedStatement.setString(1,name);// 执行SQL语句并接收结果集resultSet preparedStatement.executeQuery(); // 这里不要传入SQL了while (resultSet.next()) {long stuId resultSet.getLong(1);String stuName resultSet.getString(2);int stuAge resultSet.getInt(3);byte stuGender resultSet.getByte(4);System.out.println(MessageFormat.format(学生编号{0},学生姓名{1}, 学生年龄{2}, 学生性别{3},stuId, stuName, stuAge, stuGender));}} catch (SQLException e) {e.printStackTrace();} finally {// 关闭资源if (resultSet ! null) {try {resultSet.close();} catch (SQLException e) {e.printStackTrace();}}if (preparedStatement ! null) {try {preparedStatement.close();} catch (SQLException e) {e.printStackTrace();}}if (connection ! null) {try {connection.close();} catch (SQLException e) {e.printStackTrace();}}}}
}上面的代码主要有两个优化的地方
1、获取数据库连接不再是单独申请而是在数据源中进行索取。
由于JDBC只是一组接口因此我们没有办法直接创建数据源对象只能通过mysql厂商提供的数据源对象来进行向上转型。而前面的获取数据连接时是每一次都需要写入URL等数据而数据源只需要获取一次即可因此我们就是直接通过mysql提供的数据源对象进行设置URL等数据。
2、在优化数据源的基础上我们还需要对SQL语句进行预编译。因此得先写一个SQL语句并且不能再是拼接字符串的方式了所以这里就用到了占位符。然后再让我们自己输入数据去填充占位符接着就可以直接进行查询了。
上面我们写的代码都是查询操作现在我们来写一个简单的新增操作。
大体操作是一致的。
import com.mysql.cj.jdbc.CallableStatement;
import com.mysql.cj.jdbc.MysqlDataSource;import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Scanner;public class JDBC_Demo3 {public static void main(String[] args) {// 定义mysql数据源对象MysqlDataSource mysqlDataSource new MysqlDataSource();// 设置数据连接串// URLmysqlDataSource.setURL(jdbc:mysql://127.0.0.1:3306/java?characterEncodingutf8 allowPublicKeyRetrievaltrueuseSSLfalse);// 用户名mysqlDataSource.setUser(root);// 密码mysqlDataSource.setPassword(123456);// 上面是厂商给我们提供的实现类我们要使用Java层面的数据源接口DataSource dataSource mysqlDataSource;Connection connection null;PreparedStatement preparedStatement null;try {// 建立连接connection dataSource.getConnection();// 定义SQL并进行预编译String sql insert into student values (?,?,?,?);preparedStatement connection.prepareStatement(sql);// 接收输入Scanner scanner new Scanner(System.in);System.out.print(请输入新增学生编号);long id Long.parseLong(scanner.next()); // 不会出现问题System.out.print(请输入新增学生姓名);String name scanner.next();System.out.print(请输入新增学生年龄);int age Integer.parseInt(scanner.next());System.out.print(请输入新增学生性别);byte gender Byte.parseByte(scanner.next());// 替换占位符preparedStatement.setLong(1,id); // 默认从1开始的preparedStatement.setString(2, name);preparedStatement.setInt(3,age);preparedStatement.setByte(4,gender);// 执行SQL语句并接收结果集int line preparedStatement.executeUpdate(); // 这里返回的是受影响的行数if (line 1) {System.out.println(新增成功);} else {System.out.println(新增失败);}} catch (SQLException e) {e.printStackTrace();} finally {// 依次关闭资源if (preparedStatement ! null) {try {preparedStatement.close();} catch (SQLException e) {e.printStackTrace();}}if (connection ! null) {try {connection.close();} catch (SQLException e) {e.printStackTrace();}}}}
}效果演示 注意
1、这里之所以全部改用next 方法是因为其他的方法可能会出现一些预料不到的问题。
2、占位符可以有多个是从1按照顺序开始的。
JDBC编程的两种方式对比
现在我们就来总结一下JDBC的简单使用过程。
第一种方式不推荐使用
1、加载数据库厂商提供的驱动包。注意一个项目中只需加载一次就类似于一个手机上面只能安装一个同样的应用程序虚拟机除外。
2、建立连接。
3、创建Statement对象
4、通过Statement对象执行SQL语句
5、处理结果集
6、关闭资源。
第二种方式推荐使用
1、 创建数据源对象。 a使用数据库厂商提供的数据源创建对象设置连接串。 b用Java提供的接口去接收进行向上转型。
2、建立连接。
3、定义SQL语句进行预编译。
4、接收真实数据代替占位符。
5、执行SQL语语并接收返回值。
6、关闭资源。
第二种方式的优点
1、主要是针对SQL注入的情况进行了预编译优化。
2、对于第一种方式频繁的建立连接关闭资源做了优化定义一个数据源每次建立连接都是通其中的某一个建立连接并且当使用完成之后也不会真的把资源关闭而是还给了数据源。
好啦本期 初始MYSQL数据库8—— JDBC编程 的学习之旅就到此结束啦我们下一期再一起学习吧