版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/someby/article/details/87936321
目录
本篇文章介绍JDBC原理介绍以及增删改查。
JDBC原理
JDBC测试
创建测试的数据表
CREATE TABLE IF NOT EXISTS `test_user`( `id` INT UNSIGNED AUTO_INCREMENT, `name` VARCHAR(100) NOT NULL, `age` INT DEFAULT NULL, PRIMARY KEY ( `id` ) )ENGINE=InnoDB DEFAULT CHARSET=utf8;
测试代码
package main.xxx.java.test; import java.sql.*; /** * FileName: JdbcCRUD * Author: hadoop * Email: [email protected] * Date: 19-2-26 下午4:09 * Description: /** * JDBC增删改查示范类 * * JDBC只是java程序操作数据库中最原始和最基础的一种方式 * * 实际上,在项目中,我们一般不会直接使用JDBC;而是会使用J2EE的一些开源框架,比如MyBatis,也可以是Hibernate * 而且为了方便框架的整合使用,我们通常都会在spark作业中,使用Spring开源框架,进行各种技术的整合 * 比如Kafka、Redis、ZooKeeper、Thrift * * MyBatis/Hibernate这种操作数据库的框架,其实底层也是基于JDBC进行封装的,只不过提供了更加方便快捷的使用 * 大大提升了我们的开发效率 * * 但是在本套系类课程中,是不会使用这些开源框架来操作数据库的,而只会使用JDBC * 因为直接用JDBC最简单,也最基础,不需要其他技术的基础 * 主要同学们有基本的java编程基础、最最基础的hadoop基础知识,以及扎实的Spark技术功底 * 我们就要保证同学们就可以学习这套高端、负责的Spark大型大数据项目实战课程 * * */ public class JdbcCRUD { public static void main(String[] args){ //insert(); //update(); //delete(); //select(); preparedStatement(); } /** * 测试插入语句 */ private static void insert(){ // 总结一下JDBC的最基本的使用过程 // 1、加载驱动类:Class.forName() // 2、获取数据库连接:DriverManager.getConnection() // 3、创建SQL语句执行句柄:Connection.createStatement() // 4、执行SQL语句:Statement.executeUpdate() // 5、释放数据库连接资源:finally,Connection.close() // 定义数据库连接对象 // 引用JDBC相关的所有接口或者是抽象类的时候,必须是引用java.sql包下的 // java.sql包下的,才代表了java提供的JDBC接口,只是一套规范 // 至于具体的实现,则由数据库驱动来提供,切记不要引用诸如com.mysql.jdbc包的类 Connection conn = null; // 定义SQL语句执行句柄:Statement对象 // Statement对象,其实就是底层会基于Connection数据库连接 // 可以让我们方便的针对数据库中的表,执行增删改查的SQL语句 // 比如insert、udpate、delete和select语句 Statement stmt = null; try { // 第一步,加载数据库的驱动,我们都是面向java.sql包下的接口在编程,所以 // 要想让JDBC代码能够真正操作数据库,那么就必须第一步先加载进来你要操作的数据库的驱动类 // 使用Class.forName()方式来加载数据库的驱动类 // Class.forName()是Java提供的一种基于反射的方式,直接根据类的全限定名(包+类) // 从类所在的磁盘文件(.class文件)中加载类对应的内容,并创建对应的Class对象 Class.forName("com.mysql.jdbc.Driver"); // 获取数据库的连接 // 使用DriverManager.getConnection()方法获取针对数据库的连接 // 需要给方法传入三个参数,包括url、user、password // 其中url就是有特定格式的数据库连接串,包括“主协议:子协议://主机名:端口号//数据库” conn = DriverManager.getConnection( "jdbc:mysql://localhost:3306/spark_project", "root", "123456" ); // 基于数据库连接Connection对象,创建SQL语句执行句柄,Statement对象 // Statement对象,就是用来基于底层的Connection代表的数据库连接 // 允许我们通过java程序,通过Statement对象,向MySQL数据库发送SQL语句 // 从而实现通过发送的SQL语句来执行增删改查等逻辑 stmt = conn.createStatement(); // 然后就可以基于Statement对象,来执行insert SQL语句了 // 插入一条数据 // Statement.executeUpdate()方法,就可以用来执行insert、update、delete语句 // 返回类型是个int值,也就是SQL语句影响的行数 String sql = "insert into test_user(name,age) values('Jack',22)"; int rtn = stmt.executeUpdate(sql); System.out.println("SQL语句影响了【" +rtn +"】行。"); }catch (Exception e){ e.printStackTrace(); // 最后一定要记得在finally代码块中,尽快在执行完SQL语句之后,就释放数据库连接 }finally { try{ if (stmt != null) stmt.close(); if (conn != null){ conn.close(); } } catch (Exception e){ e.printStackTrace(); } } } /** * 测试更新语句 */ public static void update(){ Connection conn = null; Statement stmt = null; try{ Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection( "jdbc:mysql://localhost:3306/spark_project", "root", "123456" ); stmt = conn.createStatement(); String sql = "update test_user set age = 25 where name = 'Jack'"; int rtn = stmt.executeUpdate(sql); System.out.println("SQL语句影响了【" +rtn +"】行。"); }catch (Exception e){ e.printStackTrace(); } finally { try{ if (stmt != null) stmt.close(); if (conn != null) conn.close(); }catch (Exception e){ e.printStackTrace(); } } } /** * 测试删除语句 */ public static void delete(){ Connection conn = null; Statement stmt = null; try{ Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection( "jdbc:mysql://localhost:3306/spark_project", "root", "123456" ); stmt = conn.createStatement(); String sql = "delete from test_user where name='Jack'"; int rtn = stmt.executeUpdate(sql); System.out.println("SQL语句影响了【" +rtn +"】行。"); }catch(Exception e){ e.printStackTrace(); }finally { try{ if(stmt != null) stmt.close(); if(conn != null) conn.close(); }catch (Exception e){ e.printStackTrace(); } } } /** * 测试查询语句 */ public static void select(){ Connection conn = null; Statement stmt = null; ResultSet rs = null; try{ Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection( "jdbc:mysql://localhost:3306/spark_project", "root", "123456" ); stmt = conn.createStatement(); String sql = "select * from test_user"; rs = stmt.executeQuery(sql); // 获取到ResultSet以后,就需要对其进行遍历,然后获取查询出来的每一条数据 while (rs.next()){ /* int id = rs.getInt(1); String name = rs.getString(2); int age = rs.getInt(3);*/ int id = rs.getInt("id"); String name = rs.getString("name"); int age = rs.getInt("age"); System.out.println("id: "+id+" name: "+ name +" age: " + age); } }catch (Exception e){ e.printStackTrace(); }finally { try{ if (stmt != null) stmt.close(); if (conn != null) conn.close(); }catch(Exception e){ e.printStackTrace(); } } } /** * 测试PreparedStatement */ public static void preparedStatement(){ Connection conn = null; /** * 如果使用Statement,那么就必须在SQL语句中,实际地去嵌入值,比如之前的insert语句 * * 但是这种方式有一个弊端,第一,是容易发生SQL注入,SQL注入,简单来说,就是,你的网页的用户 * 在使用,比如论坛的留言板,电商网站的评论页面,提交内容的时候,可以使用'1 or 1',诸如此类的 * 非法的字符,然后你的后台,如果在插入评论数据到表中的时候,如果使用Statement,就会原封不动的 * 将用户填写的内容拼接在SQL中,此时可能会发生对数据库的意外的损坏,甚至数据泄露,这种情况就叫做 * SQL注入 * * 第二种弊端,就是性能的低下,比如insert into test_user(name,age) values('张三',25) * insert into test_user(name,age) values('李四',26) * 其实两条SQL语句的结构大同小异,但是如果使用这种方式,在MySQL中执行SQL语句的时候,却需要对 * 每一条SQL语句都实现编译,编译的耗时在整个SQL语句的执行耗时中占据了大部分的比例 * 所以,Statement会导致执行大量类似SQL语句的时候的,性能低下 * * 如果使用PreparedStatement,那么就可以解决上述的两个问题 * 1、SQL注入,使用PreparedStatement时,是可以在SQL语句中,对值所在的位置使用?这种占位符的 * 使用占位符之后,实际的值,可以通过另外一份放在数组中的参数来代表。此时PreparedStatement会对 * 值做特殊的处理,往往特殊处理后,就会导致不法分子的恶意注入的SQL代码失效 * 2、提升性能,使用PreparedStatement之后,其实结构类似的SQL语句,都变成一样的了,因为值的地方 * 都会变成?,那么一条SQL语句,在MySQL中只会编译一次,后面的SQL语句过来,就直接拿编译后的执行计划 * 加上不同的参数直接执行,可以大大提升性能 */ PreparedStatement pstmt = null; try{ Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection( "jdbc:mysql://localhost:3306/spark_project", "root", "123456" ); //第一个,SQL语句中,值所在的地方,都用?代表 String sql = "insert into test_user(name,age) values(?,?)"; pstmt = conn.prepareStatement(sql); // 第二个,必须调用PreparedStatement的setX()系列方法,对指定的占位符设置实际的值 pstmt.setString(1,"ZOOker"); pstmt.setInt(2,25); // 第三个,执行SQL语句时,直接使用executeUpdate()即可,不用传入任何参数 int rtn = pstmt.executeUpdate(); System.out.println("SQL语句影响了【" +rtn +"】行。"); }catch(Exception e){ e.printStackTrace(); }finally { try{ if(pstmt != null) pstmt.close(); if (conn != null) conn.close(); }catch (Exception e){ e.printStackTrace(); } } } }