JDBC连接过程:

import java.sql.*;/*** Description:* Created by CWG on 2020/10/29 21:05*/
public class ConnectionTest {public static void main(String[] args){String user = "root";String password = "cheng";String url = "jdbc:mysql://localhost:3306/mysql?serverTimezone=UTC";String driver = "com.mysql.cj.jdbc.Driver";Connection conn = null;Statement stm = null;try{Class.forName(driver);    //1.将mysql驱动注册到DriverManager中去conn = DriverManager.getConnection(url,user,password);    //2. 建立连接stm = conn.createStatement();    // 3. 创建一个Statement 实例用于发送sql语句stm.execute("sql语句")   //4.执行sql语句} catch (Exception e) {e.printStackTrace();}}
}

大概流程是这样:

  1. 首先第一步装载驱动,个人理解就是:从DriverManager名字来看,该对象是来做sql语句跟数据库数据交互的一个中间者,其功能实现还是靠com.mysql.cj.jdbc.Driver类完成。
    从源码看出,其继承NonRegisteringDriver类并实现java.sql.Driver接口,可以自查源码发现com.mysql.cj.jdbc.Driver类功能都是继承自NonRegisteringDriver类。JDBC规范要求Driver类(com.mysql.cj.jdbc)在使用前必须向DriverManger注册自己。注册过程在Driver类的静态代码块中实现。也就是说只要类被加载,就完成了向驱动管理器的注册。
public class Driver extends NonRegisteringDriver implements java.sql.Driver {public Driver() throws SQLException {}static {try {DriverManager.registerDriver(new Driver());} catch (SQLException var1) {throw new RuntimeException("Can't register driver!");}}
}
  1. 接着就是建立连接以及通过conn.createStatement()创建一个Statement实例,用来传递sql语句。
  2. 然后执行sql语句,步骤3-4有几点需要注意:
    (1)步骤3中,除了conn.createStatement() 创建Statement实例,还可以通过conn.prepareStatement 来创建PreparedStatement实例。
    (2)步骤4中,stm.execute 是一个通用执行sql语句方法,除此之外还有executeQueryexecuteUpdate方法。
    具体区别后边讲。

JDBC创建表:

stm.execute("create table users(" +"id int AUTO_INCREMENT," +"name VARCHAR(20), " +"age int," +"sex char(2)," +"PRIMARY KEY (id));");

根据上边连接好的数据库,执行以上语句来创建一个users用户表,其语句格式跟mysql完全一样,只是写成了字符串。另外注意AUTO_INCREMENT自增约束只能用于主键。


JDBC操作数据:

  • 插入数据
 stm.execute("INSERT into users(name,age,sex) VALUES ('小王',23,'男')");stm.execute("INSERT into users(name,age,sex) VALUES ('小猪',16,'女')");stm.execute("INSERT into users(name,age,sex) VALUES ('小李',18,'男')");stm.execute("INSERT into users(name,age,sex) VALUES ('小菜',23,'女')");//批量操作方式
String sql0 = "INSERT into users(name,age,sex) VALUES ('小王',23,'男')";
String sql1 = "INSERT into users(name,age,sex) VALUES ('小猪',16,'女')";
String sql2 = "INSERT into users(name,age,sex) VALUES ('小李',18,'男')";
String sql3 = "INSERT into users(name,age,sex) VALUES ('小菜',23,'女')";
stm.addBatch(sql0);
stm.addBatch(sql1);
stm.addBatch(sql2);
stm.addBatch(sql3);stm.executeBatch();
  • 查询数据
stm.execute("SELECT * from users where sex = '男'");

问题来了:插入数据没问题,然而查询数据虽然也正常执行,但是却没返回要查询的数据。另外这里的sql语句只能是静态的,若想在sql语句中传入参数,如何处理?这里就是上边提到的那两点。下边具体说明。


Statement和 PreparedStatement:

从功能上来讲,PreparedStatement可以通过参数传递方式来执行sql语句,参数位置用占位符 表示。而Statement没有这样的机制,只能写实际的字符串sql语句。

stm = conn.createStatement();
String name = "小白";
String age = "17";
String sex = "男";
String sql = "insert into users(name,age,sex) values('"+ name + "',"+ age +",'"+ sex +"')";
stm.execute(sql);

Statement方式传递参数,只能通过字符串拼串来实现,整体还是一个字符串语句。另外注意拼串时,属性name、sex这些字符串属性的单引号不可省略。

PreparedStatement ps = null;
try{Class.forName(driver);conn = DriverManager.getConnection(url,user,password);String sql = "insert into users(name,age,sex) values(?,?,?)";ps = conn.prepareStatement(sql);ps.setString(1,"小灰");ps.setInt(2,21);ps.setString(3,"女");ps.execute();} catch (Exception e) {e.printStackTrace();}

到这里表中数据(id不连续主要自己删了一行,这里不要在意)

PreparedStatement方式实现sql语句执行,sql语句中先通过来占位,然后通过setXX方法来拼串,方法中第一个参数代表第几个参数。

  • 两种方式区别:
  1. 效率问题:Statement每次执行sql语句,相关数据库都要执行sql语句的编译;PreparedStatement是预编译的(插入的参数不再编译), 采用Cache机制(预编译语句,放在Cache中,下次执行相同SQL语句时,则可以直接从Cache中取出来,对于批量处理可以大大提高效率。
  2. PrepareStatement中执行的SQL语句中是可以带参数的,也就是说可以替换变量,尽量采用使用?号的方式传递参数,增加代码的可读性又可以预编译加速;而Statement则不可以。
  3. 防止SQL注入:在SQL中包含特殊字符或SQL的关键字时,Statement将出现不可预料的结果,可用PreparedStatement来解决,因为插入的参数不会再进行编译,比较安全。
    以上3点摘自:https://www.cnblogs.com/gbb123/p/7053772.html

SQL注入问题:
比如有这样一个情况:

String table = user; delete user;-- ; // 表名为 user; delete user;--
String name = "admin";
有如下select语句
String sql = "select * from " + table + "where name = '" + name +"'";

Statement进行sql语句解析为:select * from user; delete user; -- where name = 'admin'; ,–后面的语句被注释,而原本查询用户的语句变成了查询所有用户信息+删除用户表的语句,如果存在user用户表,则信息全被删了。
而PreparedStatement会将传入的参数全当作字符串来处理,不会对传入参数进行编译,因此可以避免该问题。虽然这里用一个恶意表名来举例,场景感不是很强,但是换一种场景,在系统登录界面,通过用户名来搞恶意注入,那问题就大了。


executeQuery、executeUpdate 和 execute:

前边有一个问题就是返回值问题,execute虽然是全能sql语句操作,可以执行任何sql语句,但其返回值类型却是boolean型,select语句执行时,如何得到查询结果?

实际上,Statement和PreparedStatement接口都提供了三种执行 SQL 语句的方法:executeQuery、executeUpdate 和 execute。

  • executeQuery 用于产生单个结果集(ResultSet,不是单行数据)的语句。
  • executeUpdate 用于执行 INSERT、UPDATE 或 DELETE 语句,SQL DDL(数据定义语言)语句,例如 CREATE TABLE 和 DROP TABLE。INSERT、UPDATE 或 DELETE 语句的效果是修改表中零行或多行中的一列或多列。executeUpdate 的返回值是一个整数(int),指示受影响的行数(即更新计数)。对于 CREATE TABLE 或 DROP TABLE 等不操作行的语句,executeUpdate 的返回值总为零。
  • execute 可用于执行任何SQL语句,返回一个boolean值,表明执行该SQL语句是否返回了ResultSet。如果执行后第一个结果是ResultSet,则返回true,否则返回false。但它执行SQL语句时比较麻烦,通常我们没有必要使用execute方法来执行SQL语句,而是使用executeQuery或executeUpdate更适合,但如果在不清楚SQL语句的类型时则只能使用execute方法来执行该SQL语句了。

以上三者区别摘自:https://www.cnblogs.com/yunqingtuo/p/10512677.html


  • execute实例:
stm = conn.createStatement();
boolean res0 = stm.execute("INSERT into users(name,age,sex) VALUES ('小C',25,'女')");
boolean res1 = stm.execute("SELECT * from users where sex = '男'");
System.out.println(res0 + "====" + res1);

返回false====true ,看出execute会在select语句中返回true,表明产生ResultSet结果集,而insert语句返回false

获取execute的结果集:

stm = conn.createStatement();
boolean res1 = stm.execute("SELECT name,age from users where sex = '男'");
ResultSet resultSet = stm.getResultSet(); //注意通过Statement实例stm获取结果集// ResultSetMetaData meta = resultSet.getMetaData(); //获取每一条元数据信息
// int columnCount = meta.getColumnCount(); //统计一条元数据有几个字段while (resultSet.next()){System.out.println("name:" + resultSet.getString("name") + ", age:" + resultSet.getInt("age"));
}


  • executeQuery实例:
ResultSet resultSet = stm.executeQuery("SELECT name,age from users where sex = '男'");
while (resultSet.next()){System.out.println("name:" + resultSet.getString("name") + ", age:" + resultSet.getInt("age"));
}

executeQuery返回值就是ResultSet,不必像execute通过stm.getResultSet()来获取结果集。


  • executeUpdate 实例:
int res = stm.executeUpdate("delete from users where sex = '男'");
System.out.println("语句executeUpdate执行后受影响的行数为:" + res);

结果:语句executeUpdate执行后受影响的行数为:3,另外executeUpdate不可以执行select操作


JDBC连接mysql、创建表、操作数据、PreparedStatement防注入、sql语句返回值类型知识汇总相关推荐

  1. 学生选课在MYSQL创建表_学生选课数据库SQL语句练习题

    一.            设有一数据库,包括四个表:学生表(Student).课程表(Course).成绩表(Score)以及教师信息表(Teacher).四个表的结构分别如表1-1的表(一)~表( ...

  2. qt连接mysql创建表_Qt编译mysql以及创建表后进行导入操作

    鉴于很多同学对Qt编译myql总是不能成功.出现各种问题,今天特此写出本教程,希望可以帮到须要的同学. 首先,须要明确编译的目的和原理. 目的:Qt 5.2版本号曾经都是不带mysql驱动的.所以须要 ...

  3. mysql 单表 子查询_MySQL基本SQL语句之单表查询、多表查询和子查询 | 旺旺知识库...

    一.简单查询: 基本语法: SELECT * FROM tb_name;查询全部 SELECT field1,field2 FROM tb_name; 投影 SELECT [DISTINCT] * F ...

  4. mysql 修改表名的方法:sql语句

    在使用mysql时,经常遇到表名不符合规范或标准,但是表里已经有大量的数据了,如何保留数据,只更改表名呢? 可以通过建一个相同的表结构的表,把原来的数据导入到新表中,但是这样视乎很麻烦. 能否简单使用 ...

  5. 【Java 虚拟机原理】Class 字节码二进制文件分析 五 ( 方法计数器 | 方法表 | 访问标志 | 方法名称索引 | 方法返回值类型 | 方法属性数量 | 方法属性表 )

    文章目录 前言 一.方法表结构 二.方法计数器 三.方法表数据解析 ( init 构造方法 ) 1.方法访问标志 2.方法名称索引 3.方法返回类型 4.方法属性数量 前言 上一篇博客 [Java 虚 ...

  6. mysql resulttype_常见的MyBatis中查询结果resultType返回值类型

    一.返回一般数据类型 比如要根据 id 属性获得数据库中的某个字段值. mapper (dao)接口: // 根据 id 获得数据库中的 username 字段的值 String getStuName ...

  7. qt连接mysql创建表_用Qt访问数据库写一个 表格

    访问数据库,将数据填充数据表格大致样子如下: 该怎么实现呢. 首先创建一个数据库模型的对象:QSqlQueryModel *model = new QSqlQueryModel; 然后提取数据库数据: ...

  8. MySQL多表关联数据同时删除sql语句

    DELETE删除多表数据,怎样才能同时删除多个关联表的数据呢?这里做了深入的解释: 代码如下 复制代码 1 delete from t1 where 条件 2 delete t1 from t1 wh ...

  9. MySQL查看表中的索引的SQL语句

    show index from student_info;        (student_info 是表名)

最新文章

  1. 【Qt】QtCreator中关于Style Plugin Example没有效果的修改方法
  2. 用delphi创建服务程式
  3. Android版本更新踩坑,Android Studio 3.0升级后踩到的坑
  4. AI又被彩虹吹?!新浪财经:应届博士算法毕业,80万年薪被疯抢
  5. java 根据类名示例化类_Java LocalDateTime类| minusMinutes()方法与示例
  6. 通过修改explorer.exe内存隐藏文件及注册表项
  7. 技术面试的《飞鸽传书2007绿色版下载》
  8. 产品创新及内容多元化 推动腾讯音乐第一季度财务和运营表现强劲
  9. azure云数据库_Azure SQL数据库的安全注意事项
  10. Spring框架最终注解标签注入方法
  11. 冬季旅游怎么搭?这样穿度假更休闲舒适
  12. 漂亮的抽奖C#源代码
  13. 浅谈数学在c语言编程中的,试论C语言程序设计中算法设计的作用
  14. 【PLC】PLCPAC入门教程
  15. 期权定价数值方法之蒙特卡洛模拟【python量化】
  16. 高通8953 Android9.0修改设备节点权限问题
  17. 智慧运维平台之全息监控
  18. Bert中文文本多分类与传统BOW+tfidf+LR中文文本多分类对比
  19. 二叉树的前序遍历-python
  20. html中设置字体字型,html中 如何在font中设置字体样式(粗体斜体等)

热门文章

  1. 码神日志N0.1|专场邀请:深度解析音视频技术(内有福利哦~)
  2. 关于cgroup的几个核心名词及其关系
  3. vue.js框架原理浅析
  4. strongswan技术
  5. 根据mysql数据库日志恢复删除数据
  6. PHP使用session_set_save_handler陷阱
  7. sklearn数据集操作API
  8. Matlab如何绘制散点图矩阵,不同版本的散点图矩阵
  9. java神雕侠侣1古墓情缘游戏攻略_《神雕侠侣》古墓派平民玩法攻略
  10. Fiddler抓包工具详解(一)(fiddler原理,HTTP请求构成)