在学习了Mysql之后,我们就要把Mysql和我们之前所学习的Java所结合起来
而JDBC就是这样一种工具:帮助我们使用Java语言来操作Mysql数据库
首先我们先来了解一下JDBC
JDBC概念:
JDBC本质:
JDBC优点:
下面我们通过JDBC的基本步骤和一段实例代码来带大家体验一下JDBC
基本步骤:
// 0.创建工程,导入驱动jar包 (资源可以在网络搜索) // 1.注册驱动 Class.forName("com.mysql.jdbc.Driver"); // 2.获得连接 Connection conn = DriverManager.getConnection(url,username,password); // 3.定义MYSQL语句 String sql = "~~~"; // 4.获得执行对象 Statement stmt = conn.createStatement(); // 5.执行SQL语句 stmt.executeUpdate(sql); // 6.处理返回结果 // 7.释放资源
实例代码:
import java.sql.Connection; import java.sql.DriverManager; import java.sql.Statement; // JDBC快速入门 public class Demo1 { public static void main(String[] arg) throws Exception{ // 1.注册驱动(这里是固定语法,是Java中的反射) Class.forName("com.mysql.jdbc.Driver"); // 2.获得连接(Connection是类,最后需要释放资源) // (url前面固定jdbc:mysql://127.0.0.1:3306/,最后加上你所需要的数据库test,username为数据库账号,password为数据库密码) String url = "jdbc:mysql://127.0.0.1:3306/test"; String username = "root"; String password = "123456"; Connection conn = DriverManager.getConnection(url,username,password); // 3.定义SQL语句(这里SQL语句与MYSQL语句相同) String sql = "update jdbc_test set age = 20 where id = 1"; // 4.获得执行SQL对象(这里也是类) Statement stmt = conn.createStatement(); // 5.执行SQL(注意这里返回的是count,是sql中受影响的行数) int count = stmt.executeUpdate(sql); // 6.返回执行结果 System.out.println(count); // 7.释放内存 stmt.close(); conn.close(); } }
JDBC中的API主要有四种,我们将在下面一一介绍:
DriverManager主要包含两个作用:
// 注册驱动是JDBC使用的第一步 Class.forName("com.mysql.jdbc.Driver"); // 上述的操作虽然是Class类的forName操作,但实际上是由Driver类的static函数组成的,如果含兴趣可以上网搜索该代码
注意:
// 2.获得连接 // (url前面固定jdbc:mysql://127.0.0.1:3306/,最后加上你所需要的数据库test,username为数据库账号,password为数据库密码) String url = "jdbc:mysql://127.0.0.1:3306/test"; String username = "root"; String password = "123456"; Connection conn = DriverManager.getConnection(url,username,password);
这里getConnection包含三个参数,username和password分别表示账号和密码,不需要解释
我们主要关注url的构造:
// 语法: jdbc:mysql://ip地址(域名):端口号/数据库名称?参数键值对1&参数键值对2... // 实例: String url = "jdbc:mysql://127.0.0.1:3306/test?useSSL=false";
注意:
最后我们给出整体代码来展现DriverManager所学到的部分:
import java.sql.Connection; import java.sql.DriverManager; import java.sql.Statement; // JDBC_DriverManager public class Demo2 { public static void main(String[] arg) throws Exception{ // 我们在MYSQL5.0以上版本可以省略注册驱动的步骤 // Class.forName("com.mysql.jdbc.Driver"); // 当我们在主机使用MYSQL时,可以省略27.0.0.1:3306 // 如果我们希望省略SSL警告语言可以设置关闭 String url = "jdbc:mysql:///test?useSSL=false"; String username = "root"; String password = "123456"; Connection conn = DriverManager.getConnection(url,username,password); String sql = "update jdbc_test set age = 20 where id = 1"; Statement stmt = conn.createStatement(); int count = stmt.executeUpdate(sql); System.out.println(count); stmt.close(); conn.close(); } }
Connection主要包含两个作用:
我们有三种方法可以获得SQL执行对象,这里先做出语法介绍,在后续我们会进行详细解释:
Statement stmt = conn.createStatement();
PreparedStatement pstmt = conn.prepareStatement(sql);
CallableStatement cstmt = conn,prepareCall(sql);
我们可以通过Connection来进行MYSQL中的事务管理
我们通过对比MYSQL的事务来解释:
# 开启事务 BEGIN; # 提交事务 COMMIT; # 回滚事务 ROLLBACK; -- mysql自动提交事务
我们的JDBC也同样提供三种方法来对应mysql事务:
// 开启事务 boolean autoCommit有两种选择:true为自动提交,false为手动提交(如果希望手动提交设置为false) conn.setAutoCommit(boolean autoCommit) // 提交事务 conn.commit(); // 回滚事务 conn.rollback();
最后我们给出整体代码来展现Connection所学到的部分:
import java.sql.Connection; import java.sql.DriverManager; import java.sql.Statement; // JDBC_Connection public class Demo3 { public static void main(String[] arg) throws Exception{ String url = "jdbc:mysql:///test?useSSL=false"; String username = "root"; String password = "123456"; Connection conn = DriverManager.getConnection(url,username,password); // 我们来研究事务的执行 (我们希望下面两条语句在一个事务中同时执行) String sql1 = "update jdbc_test set age = 16 where id = 1"; String sql2 = "update jdbc_test set age = 16 where id = 2"; Statement stmt = conn.createStatement(); // 我们需要在try中进行,因为为了当出错时可以采用回滚方法 try { // 开启事务 conn.setAutoCommit(false); int count1 = stmt.executeUpdate(sql1); System.out.println(count1); int count2 = stmt.executeUpdate(sql2); System.out.println(count2); // 提交事务 conn.commit(); } catch (Exception e){ // 出错时回滚事务 conn.rollback(); } stmt.close(); conn.close(); } }
Statement只有一个作用:执行SQL语句
Statement的执行方式主要分为两种:
Statement可以执行Update操作,主要针对mysql的DML和DDL操作
// 下述是Statement执行DML和DDL操作的语法,sql为String类型的mysql语句 int count = stmt.executeUpdate(sql); // 注意:返回值是DML和DDL语句所影响的行数
下面我们给出整体案例解释Statement的executeUpdate操作:
import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; // JDBC_DriverManager public class Demo4 { public static void main(String[] arg) throws Exception{ } public static void test_DML() throws SQLException { String url = "jdbc:mysql:///test?useSSL=false"; String username = "root"; String password = "123456"; Connection conn = DriverManager.getConnection(url,username,password); String sql = "update jdbc_test set age = 20 where id = 1"; Statement stmt = conn.createStatement(); int count = stmt.executeUpdate(sql); // 我们在实际页面制作时,需要给用户反馈是否成功 // 对于DML语句,当count>0时基本为操作成功 if(count>0){ System.out.println("操作成功!"); }else { System.out.println("操作失败~"); } stmt.close(); conn.close(); } public static void test_DDL() throws SQLException { String url = "jdbc:mysql:///test?useSSL=false"; String username = "root"; String password = "123456"; Connection conn = DriverManager.getConnection(url,username,password); String sql = "update jdbc_test set age = 20 where id = 1"; Statement stmt = conn.createStatement(); int count = stmt.executeUpdate(sql); // 我们在实际页面制作时,需要给用户反馈是否成功 // 对于DDL语句,DROP时count为0,所以不能用count判断,基本情况下不报错即为成功 stmt.close(); conn.close(); } }
Statement可以执行Query操作,主要针对mysql的DQL操作
// 下述是Statement执行DQL操作的语法,sql为String类型的mysql语句 ResultSet resultSet = stmt.executeQuery(sql); // 注意:ResultSet是stmt.executeQuery的返回类型,下面我们将着重介绍一下
ResultSet的作用:
那么如何获得ResultSet所储存的值:
// ResultSet具有next()方法,其作用是:将当前光标向前移动一行,并判断当前行是否为有效行并返回true或false // ResultSet在获得结果后的光标指向目录行,移动一行后得到第一行数据, boolean next(): /* true:表示当前行有数据,可以提取或者直接输出搜索成功 false:表示当前行没有数据,表示搜索失败 */
// ResultSet具有getXxx(参数)方法,其作用是获得当前行保存的数据 Xxx name = resultSet.getXxx(参数); /* Xxx 表示数据类型:Int,Double,String等 参数有两种: 1.数字参数,表示列数 2.字符串参数,表示列名 */
// 具体遍历采用while语法 while(rs.next()){ //获得数据 int i = rs.getInt(1); }
下面我们给出整体案例解释Statement的executeQuery操作:
import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; // JDBC_SQL public class Demo5 { public static void main(String[] arg) throws Exception{ String url = "jdbc:mysql://127.0.0.1:3306/test?useSSL=false"; String username = "root"; String password = "123456"; Connection conn = DriverManager.getConnection(url,username,password); // 我们接下来讲解SQL,因为SQL所获得的数据类型为ResultSet,所以我们单独讲解 // 先设置SQL语句 String sql = "select * from jdbc_test"; // 然后获得对象 Statement stmt = conn.createStatement(); // 然后开始执行语句 ResultSet resultSet = stmt.executeQuery(sql); // 然后我们循环得到数据 // next最开始指向非数据行,然后开始执行:向下运行一行,并且判断是否为有效行 while (resultSet.next()){ // 当为有效行,获得数据(可以通过列数,也可以通过列名) int id = resultSet.getInt("id"); String string = resultSet.getString(2); int age = resultSet.getInt("age"); System.out.println(id); System.out.println(string); System.out.println(age); System.out.println("----------------"); } // 释放资源 resultSet.close(); stmt.close(); conn.close(); } }
我们再给出一个mysql和Java结合的常用案例:
import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; import java.util.ArrayList; import java.util.List; import pojo.Student; // JDBC_SQL案例演示 // 查询jdbc_test数据库,封装进Student对象,并存储到ArrayList集合中 public class Demo6 { public static void main(String[] arg) throws Exception{ // 创建集合 List<Student> list = new ArrayList<>(); String url = "jdbc:mysql://127.0.0.1:3306/test?useSSL=false"; String username = "root"; String password = "123456"; Connection conn = DriverManager.getConnection(url,username,password); // 先设置SQL语句 String sql = "select * from jdbc_test"; // 然后获得对象 Statement stmt = conn.createStatement(); // 然后开始执行语句 ResultSet resultSet = stmt.executeQuery(sql); // 然后我们循环得到数据 while (resultSet.next()){ // 创建对象 Student s = new Student(); int id = resultSet.getInt("id"); String string = resultSet.getString(2); int age = resultSet.getInt("age"); // 赋值 s.setId(id); s.setName(string); s.setAge(age); // 把对象插入集合 list.add(s); } // 我们查看结果 System.out.println(list); // 释放资源 resultSet.close(); stmt.close(); conn.close(); } }
PreparedStatement的作用有两个:
首先我们先来介绍SQL注入问题:
我们给出一段Web端之前的账号登录匹配代码:
import com.itheima.pojo.Account; import org.junit.Test; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; import java.util.ArrayList; import java.util.List; /** * 用户登录 */ public class JDBCDemo6_UserLogin { @Test public void testLogin() throws Exception { //2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写 String url = "jdbc:mysql:///db1?useSSL=false"; String username = "root"; String password = "1234"; Connection conn = DriverManager.getConnection(url, username, password); // 接收用户输入 用户名和密码(这里直接写入,我们会在JavaWeb部分学到交互) String name = "zhangsan"; String pwd = "fhsjkfhdsk"; String sql = "select * from tb_user where username = '"+name+"' and password = '"+pwd+"'"; // 获取stmt对象 Statement stmt = conn.createStatement(); // 执行sql ResultSet rs = stmt.executeQuery(sql); // 判断登录是否成功 if(rs.next()){ System.out.println("登录成功~"); }else{ System.out.println("登录失败~"); } //7. 释放资源 rs.close(); stmt.close(); conn.close(); } }
我们可以注意到上述的sql语句采用的是字符串拼接,
因而当我们采用一些特殊字符时,就会导致mysql的搜索语句变为true,搜索到所有的mysql内容然后进入第一个账号
import com.itheima.pojo.Account; import org.junit.Test; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; import java.util.ArrayList; import java.util.List; /** * 用户登录 */ public class JDBCDemo6_UserLogin { /** * 演示SQL注入 * @throws Exception */ @Test public void testLogin_Inject() throws Exception { //2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写 String url = "jdbc:mysql:///db1?useSSL=false"; String username = "root"; String password = "1234"; Connection conn = DriverManager.getConnection(url, username, password); // 接收用户输入 用户名和密码 String name = "hfkjsfhskj"; // 注意这里"' or '1' = '1"带入到sql语句中就会导致变为select * from tb_user where true String pwd = "' or '1' = '1"; String sql = "select * from tb_user where username = '"+name+"' and password = '"+pwd+"'"; System.out.println(sql); // 获取stmt对象 Statement stmt = conn.createStatement(); // 执行sql ResultSet rs = stmt.executeQuery(sql); // 判断登录是否成功 if(rs.next()){ System.out.println("登录成功~"); }else{ System.out.println("登录失败~"); } //7. 释放资源 rs.close(); stmt.close(); conn.close(); }
因而我们采用PreparedStatement来预防SQL注入问题
我们先来介绍PreparedStatement的语法:
// 获得PreparedStatement对象 // 首先我们需要设置sql语句,并且将参数用?代替 String sql = "select * from table where usename = ? and password = ?"; // 我们在创建PreparedStatement对象时需要直接将sql语句带入 PreparedStatement pstmt = conn.PreparedStatement(sql); // 然后我们需要设置参数值 pstmt.setXxx(参数1,参数2); /* Xxx: 数据类型,包括Int,Double,String等 参数1:?的位置编号,从1开始 参数2:?的值 */ // 最后执行SQL pstmt.executeQuery();
下面我们给出整体案例解释PreparedStatement操作:
import org.junit.Test; import java.sql.*; import java.util.Date; /** * API详解:PreparedStatement */ public class JDBCDemo7_PreparedStatement { @Test public void testPreparedStatement() throws Exception { //2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写 String url = "jdbc:mysql:///db1?useSSL=false"; String username = "root"; String password = "1234"; Connection conn = DriverManager.getConnection(url, username, password); // 接收用户输入 用户名和密码 String name = "zhangsan"; String pwd = "' or '1' = '1"; // 定义sql String sql = "select * from tb_user where username = ? and password = ?"; // 获取pstmt对象 PreparedStatement pstmt = conn.prepareStatement(sql); // 设置?的值 pstmt.setString(1,name); pstmt.setString(2,pwd); // 执行sql ResultSet rs = pstmt.executeQuery(); // 判断登录是否成功 if(rs.next()){ System.out.println("登录成功~"); }else{ System.out.println("登录失败~"); } //7. 释放资源 rs.close(); pstmt.close(); conn.close(); } }
然后我们稍微拓展一下为什么PreparedStatement为什么不会导致字符串拼接错误:
PreparedStatement预编译原理:
首先我们对数据库连接池做出简单介绍:
数据库连接池优点:
我们采用通俗解释来说:
我们的数据库会有很多人访问,每当来一个人操作数据库,MYSQL创建一个Connection,在这个人使用后,再将Connection删除,
这种资源重复创造删除,导致数据库效率低下
我们的数据库具有一定的Connection数量,当每来一个人,MYSQL分配给它一个Connection,并在使用后回收;
如果这个人的使用时间超过正常时间,MYSQL将会自动回收
我们从三个方法讲解数据库连接池的实现:
标准接口:DataSource
Connection conn = DataSource.getConnection();
常见数据库连接池:
Druid(德鲁伊)
Druid的使用分为五步:
我们给出实例代码:
# 定义配置文件 driverClassName=com.mysql.jdbc.Driver url=jdbc:mysql:///db1?useSSL=false&useServerPrepStmts=true username=root password=1234 # 初始化连接数量 initialSize=5 # 最大连接数 maxActive=10 # 最大等待时间 maxWait=3000
import com.alibaba.druid.pool.DruidDataSourceFactory; import javax.sql.DataSource; import java.io.FileInputStream; import java.sql.Connection; import java.util.Properties; /** * Druid数据库连接池演示 */ public class DruidDemo { public static void main(String[] args) throws Exception { //1.导入jar包(在网上可以找到,同JDBC包一样) //2.定义配置文件 //3. 加载配置文件 Properties prop = new Properties(); prop.load(new FileInputStream("jdbc-demo/src/druid.properties")); //4. 获取连接池对象 DataSource dataSource = DruidDataSourceFactory.createDataSource(prop); //5. 获取数据库连接 Connection Connection connection = dataSource.getConnection(); System.out.println(connection); //System.out.println(System.getProperty("user.dir")); } }
好的,关于JDBC的内容我们就讲解到这里!
该文章属于学习笔记,主要学习B站黑马JDBC视频
这里附上链接:黑马JDBC视频全套视频教程,快速入门jdbc原理+jdbc实战,一套掌握_哔哩哔哩_bilibili