JDBC详解 不念不忘少年蓝@ 2024-03-30 17:28 38阅读 0赞 **目录** 一、JDBC简介 二、JDBC的快速入门 三、DriverManager详解 1. 注册驱动 2.获取数据库连接 四、Connection详解 1.获取执行SQL的对象 2.事务管理 五、Statement详解 六、ResultSet详解 ResultSet(结果集对象)作用: 获取查询结果 使用步骤 ResultSet案例 七、PreparedStatement详解 PrepareStatement作用 PrepareStatement用法步骤 PreparedStatement的好处 PreparedStatement的原理: -------------------- ### 一、JDBC简介 ### * **JDBC就是用Java语言操作关系型数据库的一套API。** * **全称:(****J****ava** **D****ata****B****ase** **C****onnectivity)Java数据库连接。** ![b1453ce2a8294c0cbe83f028568cb1b6.png][] **JDBC本质:**同一套Java代码,操作不同类型的关系型数据库。 * 官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口。 * 各个数据库厂商去实现这套接口,提供数据库驱动jar包。 * 我们可以使用这套接口(JDBC) 编程,真正执行的代码是驱动jar包中的实现类。 ### 二、JDBC的快速入门 ### **步骤:** **①创建工程,导入驱动jar包** ![f9d5d067597242968ae84618b621a001.png][] 1. 配置: ![e2ab10e94ad948aea862df268a9d01de.png][] 2. 导入jar包: ![f3ce9d59900a4befb204cb7b8be0b0d9.png][] 3. 右键点击jar包,将jar包添加到本项目中 ![db20ca92abd6431d935568a938b3c598.png][] ![86e04c3dde4746c7a3cabe7c021aa59a.png][] **②注册驱动** > Class.forName("com.mysql.jdbc.Driver"); **③获取连接** > Connection conn = DriverManager.getConnection(url,username,password); **④定义sql语句** > String sql = "update..."; **⑤获取执行sql对象** > Statement stmt = conn.creatStatement(); **⑥执行sql** > stmt.executeUpdate(sql); **⑦处理返回结果** **⑧释放资源** package com.itheima.jdbc; import java.sql.Connection; import java.sql.DriverManager; import java.sql.Statement; /* * JDBC快速入门 */ public class JDBCDemo { public static void main(String[] args) throws Exception { //1.注册驱动 Class.forName("com.mysql.jdbc.Driver"); //2.获取连接 String url = "jdbc:mysql://127.0.0.1:3306/db1";//固定写法,只需修改db1数据库名来连接不通的数据库 String username = "root"; String password = ""; Connection conn = DriverManager.getConnection(url, username, password); //3. 定义sql语句 String sql = "update account set money = 2000 where id = 1"; //4.获取执行sql的对象Statement Statement stmt = conn.createStatement(); //5.执行sql int count = stmt.executeUpdate(sql);//受影响的行数 //6.处理结果 System.out.println(count); //7.释放资源 stmt.close(); conn.close(); } } ### 三、DriverManager详解 ### * DriverManager(驱动管理类)作用: * 1.注册驱动 * 2.获取数据库连接 #### **1. 注册驱动** #### Class.forNae("com.mysql.jdbc.Driver");//可以省略不写 查看Driver源代码: ![f268762005af443cad2aa4682e62bbee.png][] tips: * MySQL5之后的驱动包,可以省略注册驱动的步骤 * 自动加载jar包中 META-INF\\services\\java.sql.Driver文件中的驱动类 #### **2.获取数据库连接** #### static Connection getConnection(String url,String user,String password); **参数:** **①url:连接路径** > **语法:jdbc:mysql://ip地址(域名):端口号/数据库名称?参数键值对1&参数键值对2...** > > **示例:jdbc:mysql://127.0.0.1:3306/db1** > > **细节:** > > * **如果连接的是本机的mysql服务器,并且mysql服务默认端口是3306,则url可以简写为:jdbc:mysql://数据库名称?参数键值对** > * **配置useSSL=false参数,禁止安全连接方式,解决警告提示** **② user:用户名** **③password:密码** ### **四、Connection详解** ### * Connection(数据库连接对象)作用: * 1.获取执行SQL的对象 * 2.管理事务 #### **1.获取执行SQL的对象** #### * 执行普通SQL对象: > Statement createStatement() * 预编译SQL的执行SQL对象:防止SQL注入 > PrepareStatement prepareStatement(sql) * 执行存储过程的对象 > CallableStatement prepareCall(sql) #### **2.事务管理** #### MySQL事务管理 > 开启事务:begin;/start transaction > > 提交事务:commit; > > 回滚事务:rollback; > > MySQL默认自动提交事务 JDBC事务管理:Connection接口中定义了三个对应的方法 > 开启事务:setAutoCommit(boolean autoCommit):true为自动提交事务,false为手动提交事务 > > 提交事务:commit\{\}; > > 回滚事务:rollback(); public static void main(String[] args) throws Exception { //1.注册驱动 //Class.forName("com.mysql.cj.jdbc.Driver");//5版本之后的mysql不需要写,jar包中META-INF中有 //2.获取连接:如果连接的是本机的mysql并且端口是默认的3306则可以简写 String url = "jdbc:mysql:///db1?useSSL=false";//固定写法,只需修改db1数据库名来连接不通的数据库,?后是参数 String username = "root"; String password = ""; Connection conn = DriverManager.getConnection(url, username, password); //3. 定义sql语句 String sql1 = "update account set money = 3000 where id = 1"; String sql2 = "update account set money = 3000 where id = 2"; //4.获取执行sql的对象Statement Statement stmt = conn.createStatement(); //快捷键ctrl+alt+t try { //开启事务 conn.setAutoCommit(false); //5.执行sql int count1 = stmt.executeUpdate(sql1);//受影响的行数 //6.处理结果 System.out.println(count1); int i = 3/0; //5.执行sql int count2 = stmt.executeUpdate(sql2);//受影响的行数 //6.处理结果 System.out.println(count2); //提交事务 conn.commit(); } catch (Exception e) { //回滚事务 conn.rollback(); e.printStackTrace(); } //7.释放资源 stmt.close(); conn.close(); } ### 五、Statement详解 ### * Statement作用:执行SQL语句 **执行SQL语句** > **int executeUpdate(sql):执行DML、DDL语句** > > 返回值:(1)DML语句影响的行数 > > (2)DDL语句执行后,执行成功也可能返回0 > ResultSet executeQuery(sql):执行DQL语句 > > 返回值:ResultQuery结果集对象 /** * JDBC API详解:Statement */ public class JDBCDemo4_Statement { /** * 执行DML语句 * @throws Exception */ @Test public void testDML() throws Exception { //1.注册驱动 //Class.forName("com.mysql.cj.jdbc.Driver");//5版本之后的mysql不需要写,jar包中META-INF中有 //2.获取连接:如果连接的是本机的mysql并且端口是默认的3306则可以简写 String url = "jdbc:mysql:///db1?useSSL=false";//固定写法,只需修改db1数据库名来连接不通的数据库,?后是参数 String username = "root"; String password = ""; Connection conn = DriverManager.getConnection(url, username, password); //3. 定义sql语句 String sql = "update account set money = 3000 where id = 5"; //4.获取执行sql的对象Statement Statement stmt = conn.createStatement(); //5.执行sql int count = stmt.executeUpdate(sql);//执行完DML语句后受影响的行数 //6.处理结果 //System.out.println(count); if(count>0){ System.out.println("修改成功!"); }else{ System.out.println("修改失败!"); } //7.释放资源 stmt.close(); conn.close(); } /** * 执行DDL语句 * @throws Exception */ @Test public void testDDL() throws Exception { //1.注册驱动 //Class.forName("com.mysql.cj.jdbc.Driver");//5版本之后的mysql不需要写,jar包中META-INF中有 //2.获取连接:如果连接的是本机的mysql并且端口是默认的3306则可以简写 String url = "jdbc:mysql:///db1?useSSL=false";//固定写法,只需修改db1数据库名来连接不通的数据库,?后是参数 String username = "root"; String password = ""; Connection conn = DriverManager.getConnection(url, username, password); //3. 定义sql语句 String sql = "drop database db2"; //4.获取执行sql的对象Statement Statement stmt = conn.createStatement(); //5.执行sql int count = stmt.executeUpdate(sql);//执行完DDL语句,返回值可能是0(如删除一个数据库) //6.处理结果 //System.out.println(count); // if(count>0){ // System.out.println("修改成功!"); // }else{ // System.out.println("修改失败!"); // } System.out.println(count); //7.释放资源 stmt.close(); conn.close(); } } ### 六、ResultSet详解 ### * #### ResultSet(结果集对象)作用: #### 封装了DQL查询语句的结果 > ResultSet stmt.executeQuery(sql):执行DQL语句,返回ResultSet对象 * #### 获取查询结果 #### > boolean next():(1)将光标从当前位置向前移动一行 > > (2)判断当前行是否为有效行 > > 返回值: > > ture:有效行,当前行有数据 > > false:无效行,当前行没有数据 > xxx getXxx(参数) :获取数据 > > xxx:数据类型;如:int getInt(参数);String getString(参数); > > 参数: > > int:列的编号,从1开始 > > String:列的名称 * #### 使用步骤: #### 1.游标向下移动一行,并判断该行是否有数据:next() 2.获取数据:getXxx(参数) > //循环判断游标是否是最后一行末尾 > > while(rs.next(())\{ > > //获取数据 > > rs.getXxx(参数); > > \} /** * 执行DQL语句 * @throws Exception */ @Test public void testResultSet() throws Exception { //1.注册驱动 //Class.forName("com.mysql.cj.jdbc.Driver");//5版本之后的mysql不需要写,jar包中META-INF中有 //2.获取连接:如果连接的是本机的mysql并且端口是默认的3306则可以简写 String url = "jdbc:mysql:///db1?useSSL=false";//固定写法,只需修改db1数据库名来连接不通的数据库,?后是参数 String username = "root"; String password = ""; Connection conn = DriverManager.getConnection(url, username, password); //3.定义SQL String sql = "select * from account"; //4.获取statement对象 Statement stmt = conn.createStatement(); //5.执行sql ResultSet rs = stmt.executeQuery(sql); //6. 处理结果,遍历rs中的所有数据 // //6.1光标向下移动一行并且判断当前行是否有数据 // while(rs.next()){ // //6.2获取数据 getXxx() // int id = rs.getInt(1); // String name = rs.getString(2); // double money = rs.getDouble(3); // // System.out.println(id); // System.out.println(name); // System.out.println(money); // System.out.println("-------"); // } //6.1光标向下移动一行并且判断当前行是否有数据 while(rs.next()){ //6.2获取数据 getXxx() int id = rs.getInt("id"); String name = rs.getString("name"); double money = rs.getDouble("money"); System.out.println(id); System.out.println(name); System.out.println(money); System.out.println("-------"); } //7.释放资源 rs.close(); stmt.close(); conn.rollback(); } #### **ResultSet案例** #### **需求:查询account账户表数据,封装在Account对象中,并且存储到ArrayList集合中** ![587f391e96ec4f0591acc7fe156cafdb.png][] //1.注册驱动 //Class.forName("com.mysql.cj.jdbc.Driver");//5版本之后的mysql不需要写,jar包中META-INF中有 //2.获取连接:如果连接的是本机的mysql并且端口是默认的3306则可以简写 String url = "jdbc:mysql:///db1?useSSL=false";//固定写法,只需修改db1数据库名来连接不通的数据库,?后是参数 String username = "root"; String password = ""; Connection conn = DriverManager.getConnection(url, username, password); //3.定义SQL String sql = "select * from account"; //4.获取statement对象 Statement stmt = conn.createStatement(); //5.执行sql ResultSet rs = stmt.executeQuery(sql); //创建集合 List<Account> list = new ArrayList<>(); //6.1 rs.next()光标向下移动一行并且判断当前行是否有数据 while(rs.next()){ Account account = new Account(); //6.2获取数据 getXxx() int id = rs.getInt("id"); String name = rs.getString("name"); double money = rs.getDouble("money"); //赋值 account.setId(id); account.setName(name); account.setMoney(money); //存入集合 list.add(account); } System.out.println(list); //7.释放资源 rs.close(); stmt.close(); conn.rollback(); } ### 七、PreparedStatement详解 ### * #### **PrepareStatement作用:** #### 预编译SQL语句并执行:防止SQL注入问题 > * SQL注入 > > **SQL注入是通过操作输入来修改事先定义好的SQL语句,用以达到执行代码对服务器进行攻击的方法。** > > * 原sql语句: > > select * from tb_user where username = 'zhangsan' and password = '123' > > * 通过操作输入来修改事先定义好的SQL语句,使之语意发生改变: > > select * from tb_user where username = '呵呵呵' and password = '' or '1' = '1' > > * 采用API:PreparedStatement后:在pstmt.setXxx时将传入的值进行转义,将转义后的内容当成文本的形式传入。 > > -- ' or '1' = '1 > select * from tb_user where username = 'hfkjsfhskj' and password = '\' or \'1\' = \'1' * #### **PrepareStatement用法步骤:** #### ①获取PreparedStatement对象 //SQl语句中的参数值,使用?占位符替代 String sql = "select * from user where username = ? and password = ? "; //通过Connection对象获取,并传入对应的sql语句 PreparedStatement pstmt = conn.prepareStatement(sql); ②设置参数值 > PreparedStatement对象:setXxx(参数1,参数2):给?赋值 > Xxx:数据类型;如setInt(参数1,参数2) > > 参数: > > 参数1:?的位置编号,从1开始 > > 参数2:?的值 ③ 执行sql //不再需要传递sql executeUpdate(); executeQuery(); **防止SQL注入用法示例:** @Test public void testPreparedStatement() throws Exception { //2.获取连接:如果连接的是本机的mysql并且端口是默认的3306则可以简写 String url = "jdbc:mysql:///db1?useSSL=false";//固定写法,只需修改db1数据库名来连接不通的数据库,?后是参数 String username = "root"; String password = ""; Connection conn = DriverManager.getConnection(url, username, password); //接受用户名和密码 String name = ",,,,"; 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(); } **需求:完成用户登陆** select * from tb_user where username = "张三" and password = '123'; /** * 演示sql注入 * @throws Exception */ @Test public void testLogin_Inject() throws Exception { //2.获取连接:如果连接的是本机的mysql并且端口是默认的3306则可以简写 String url = "jdbc:mysql:///db1?useSSL=false";//固定写法,只需修改db1数据库名来连接不通的数据库,?后是参数 String username = "root"; String password = ""; Connection conn = DriverManager.getConnection(url, username, password); //接受用户名和密码 String name = "shhiiii"; 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("登陆失败!"); } } * #### **PreparedStatement的好处:** #### 1.预编译SQL,性能高 2.防止SQL注入:将敏感字符义 ![ac10d470ceec45e9869cc906df0a991b.png][] ①PreparedStatement预编译功能开启:useServerPrepStmts=true ②配置MySQL执行日志(重启mysql服务后生效) > log-output=FILE > general-log=1 > general\_log\_file="G:\\MySQL\\mysql.log" > slow-query-log=1 > slow\_query\_log\_file="G:\\MySQL\\mysql\_show.log" > long\_query\_time=2 * #### **PreparedStatement的原理:** #### * **1.在获取PreparedStatement对象时,将sql语句发送给mysql服务器进行检查,编译(这些步骤比较耗时)** * **2.执行时就不用再进行这些步骤了,速度更快** * **3.如果sql模板一样,则只需要进行一次检查、编译** [b1453ce2a8294c0cbe83f028568cb1b6.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/30/8d81e1f396224314af8236e19c093270.png [f9d5d067597242968ae84618b621a001.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/30/cdcb979ed937426e84d85f311c5cb3b0.png [e2ab10e94ad948aea862df268a9d01de.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/30/22af81e667db4c61bf4f52317f6db87a.png [f3ce9d59900a4befb204cb7b8be0b0d9.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/30/0d1b4982fb294145a8f7abe9a29ddde3.png [db20ca92abd6431d935568a938b3c598.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/30/918d8d66943f499ab7f2a806d98ffef9.png [86e04c3dde4746c7a3cabe7c021aa59a.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/30/c318657d00db4031bbde95555bedfbb2.png [f268762005af443cad2aa4682e62bbee.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/30/abdb2358effa4925810989515f809f88.png [587f391e96ec4f0591acc7fe156cafdb.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/30/a8514960941e4a87bfdeb841a0533bc6.png [ac10d470ceec45e9869cc906df0a991b.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/30/3c3778ba80e045c3a4f027bc06586444.png
相关 JDBC详解 目录 一、JDBC简介 二、JDBC的快速入门 三、DriverManager详解 1. 注册驱动 2.获取数据库连接 四、Connection详解 1.获 不念不忘少年蓝@/ 2024年03月30日 17:28/ 0 赞/ 39 阅读
相关 JDBC 详解 一、JDBC快速入门 1.jdbc的概念 JDBC(Java DataBase Connectivity,java数据库连接)是一种用于执行SQL语句的Jav 落日映苍穹つ/ 2024年03月23日 18:06/ 0 赞/ 38 阅读
相关 JDBC详解 目录 一、JDBC基本概念 1、概念 2、JDBC本质 二、JDBC快速入门 1、步骤 2、代码示例 三、JDBC各个对象详解 1、DriverManager驱 红太狼/ 2023年10月19日 08:05/ 0 赞/ 72 阅读
相关 JDBC详解 JDBC 1、什么是JDBC? JDBC 全称是 java DataBase Connectivity,是java连接数据库的规范和 API。该规范中定义了一系列的 逃离我推掉我的手/ 2023年09月28日 11:16/ 0 赞/ 79 阅读
相关 JDBC详解 一、介绍 为了能让 程序 操作 数据库,对数据库中的 表 进行操作,每一种数据库都会提供一套连接和操作该数据库的驱动。而且每种数据库的驱动都各不相同,例如:mysql数据 骑猪看日落/ 2022年12月23日 07:09/ 0 赞/ 166 阅读
相关 JDBC 详解 首先是官方文档: [https://docs.oracle.com/javase/tutorial/jdbc/basics/index.html][https_docs.or 蔚落/ 2022年10月22日 04:10/ 0 赞/ 157 阅读
相关 JDBC详解 JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用 你的名字/ 2021年12月15日 14:29/ 0 赞/ 229 阅读
相关 JDBC详解 【一】JDBC介绍 1.JDBC(Java Data Base Connectivity,java数据库连接)是一种执行SQL语句的JavaAPI,可以为多种关系型数据库 水深无声/ 2021年10月01日 06:16/ 0 赞/ 377 阅读
还没有评论,来说两句吧...