什么是jdbc

JDBC(Java DataBase Connectivity)是Java和数据库之间的一个桥梁,是一个规范而不是一个实现,能够执行SQL语句。它由一组用Java语言编写的类和接口组成。各种不同类型的数据库都有相应的实现,本文中的代码都是针对MySQL数据库实现的
jdbc的工作原理:
jdbc主要由jdbc api、jdbc Driver Manager和jdbc驱动组成。
工作原理如图:
MySQL 第七章 - 图1
JDBCAPI:是jdbc的武器库,开发者可以使用里面的类与接口实现与数据的连接和操作
如:Connection(连接接口)、Statement接口、ResultSet(结果集)接口PreparedStatement接口等。

JDBC Driver Manager:
是JDBC体系结构的支柱,他负责管理各种JDBC驱动(如MYSQL数据库或Oracle数据库的JDBC驱动等)。 JDBC Driver Manager位于JDK的java.sql包中。
JDBC驱动:
JDBC驱动不包含在JDK要导入相关架包架包如下:
MySQL 第七章 - 图2
JDBC API:
是Java应用程序与各种数据库交互的标准接口,功能就是建立与数据库的连接,执行sql语句和拿到返回结果。
JDBC的主要类/接口的功能如下:
1)与数据库建立连接
>DriverManager类:装载驱动程式,并且创建新的数据库连接提供支持
>Connection接口:负责连接数据库并承但传输数据的任务.
2)发送sql语句:
>Statement接口:由Connection产生,负责执行sql语句。
>PreparedStatement接口:Statement的子接口,也由Connection产生,同样负责执行Sql语句。
比Statement接口相比具有更高的安全性。性能更高、可读性更高、维护也比较容易
3)放回处理结果
>ResultSet接口:负责保存和处理Statement执行后的查询结果.
使用JDBC连接数据库的方法:
1.加载JDBC驱动
2.与数据库建立连接
3.发送sql语句,并得到放回结果
4.处理放回结果

jdbc访问数据库的步骤

//1.加载驱动
//2.建立连接
//3.创建执行对象
//4.开始执行SQL
//5.处理执行结果
//6.释放资源

使用Class.forName(要先导入架包)

  1. try{
  2. Class.forName("JDBC驱动类的名称");
  3. }catch(ClassNotFoundException e){
  4. //处理异常代码
  5. }

使用DriverManager建立连接:
语法如下:
jdbc:数据库(是数据库的款式如:mysql)://ip:端口/数据库名称[?连接参数=参数值];
其中:
>数据库是:JDBC连接的目标数据库,如mysql数据库
>ip:JDBC所连接的目标数据库地址,如果是本地数据库,则可以是localhost
>端口:连接数据库的端口号,如果连接的是MySQL则是3306
>数据库名称:则是目标数据库的名称如hospital
>连接参数:时区

  1. jdbc:mysql://localhost:3306/hospital?serverTimezone=GMT-8

Connection是数据库连接对象的类型
常用方法

方法 作用
Statement createStatement() 创建一个Statement对象将SQL语句发送到数据库
PreparedStatement prepareStatement(String sql) 创建一个PreparedStatement对象,将参数化的SQL语句发送到数据库
boolean isClosed() 查询此Connection对象是否已经被关闭。如果已关闭,则返回true;否则返回false
void close() 立即释放此Connection对象的数据库和JDBC资源

关键代码模块:
MySQL 第七章 - 图3
常见错误:
使用JDBC连接数据库时,经常出现的错误
JDBC驱动类的名称书写错误,导致ClassNotFoundException异常
数据连接字符串、数据库用户名、密码错误,导致SQLException异常
数据库操作结束后,没有关闭数据库连接,导致仍旧占有系统资源
关闭数据库连接语句没有放到finally语句块中,导致语句可能没有被执行
Statement接口:
Java执行数据库操作的一个重要接口
在已经建立数据库连接的基础上,向数据库发送要执行的SQL语句
分类
Statement对象:执行不带参数的简单SQL语句
PreparedStatement对象:执行带或不带In参数的预编译SQL语句
常用方法

方法 作用
ResultSet executeQuery(String sql) 可以执行SQL查询并获取ResultSet对象
int executeUpdate(String sql) 可以执行插入、删除、更新的操作,返回值是执行该操作所影响的行数
boolean execute(String sql) 可以执行任意SQL语句。如果结果为 ResultSet 对象,则返回 true;如果其为更新计数或者不存在任何结果,则返回false

出String类和StringBuffer类的共同点和不同点
String类
字符串常量一旦声明则不可改变
String类对象可以改变,但改变的是其内存地址的指向
使用“+”作为数据的连接操作
不适用频繁修改的字符串操作
StringBuffer类
StringBuffer类对象能够被多次修改,且不产生新的未使用对象
使用append()方法进行数据连接
适用于字符串修改操作
是线程安全的,支持并发操作,适合多线程
如果使用StringBuffer生成了String类型字符串,可以通过toString( )方法将其转换为一个String对象
使用Statement接口执行插入数据的操作的方法
executeUpdate()方法
execute()方法
如果希望得到插入成功的数据行数,可以使用executeUpdate()方法;否则,使用execute()方法
实现步骤
声明Statement变量
创建Statement对象
构造SQL语句
执行数据插入操作
关闭Statement对象
使用PreparedStatement接口操作数据库
为什么使用PreparedStatement:
可以避免sql注入攻击
sql注入攻击:
通过提交一段SQL代码,执行超出用户访问权限的数据操作称为SQL注入(SQL Injection)
SQL注入攻击是应用安全领域的一种常见攻击方式,会造成的数据库安全风险包括:刷库、拖库和撞库等
主要是没有对用户输入数据的合法性进行判断,导致应用程序存在安全隐患
PreparedStatement常用方法:

方 法 作 用
boolean execute() 执行SQL语句,可以是任何SQL语句。如果结果是Result对象,则返回true。如果结果是更新计数或没有结果,则返回false
ResultSet executeQuery() 执行SQL查询,返回该查询生成的ResultSet对象
int executeUpdate() 执行SQL语句,该语句必须是一个DML语句,比如:INSERT、UPDATE或DELETE语句;或者是无返回内容的SQL语句,比如DDL语句。返回值是执行该操作所影响的行数
void setXxx(int index,xxx x) 方法名Xxx和第二个参数的xxx均表示(如int,float,double等)基本数据类型,且两个类型需一致,参数列表中的x表示方法的形式参数。
把指定数据类型(xxx)的值x设置给index位置的参数。根据参数类型的不同,常见方法有:
setInt(int index,int x) 、setFloat(int index,float x)、
setDouble(int index,double x)等
void setObject(int index,Object x) 除基本数据类型外,参数类型也可以是Object,可以将Object对象x设置给index位置的参数

与Statement接口相比,具有的优势
可读性和可维护性高
SQL语句执行性能高
安全性更高
jdbc连接数据库查询的案例:

  1. import org.apache.logging.log4j.LogManager;
  2. import org.apache.logging.log4j.Logger;
  3. import java.sql.*;
  4. public class HospitalQuery {
  5. private static Logger logger = LogManager.getLogger(HospitalQuery.class.getName());
  6. public static void main(String[] args) {
  7. Connection conn = null;
  8. Statement stmt = null;
  9. ResultSet rs=null;
  10. //1.记载驱动
  11. try {
  12. Class.forName("com.mysql.jdbc.Driver");
  13. } catch (ClassNotFoundException e) {
  14. logger.error(e);
  15. }
  16. try {
  17. //2.建立连接
  18. conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/hospital?serverTimezone=GMT-8&useUnicode=true&characterEncoding=utf-8", "cty", "cty");
  19. //3.常见Statement
  20. stmt = conn.createStatement();
  21. //构造sql
  22. String sql="select patientID,patientName,gender,address from patient limit 3;";
  23. //执行查询操作
  24. rs=stmt.executeQuery(sql);
  25. //移动光标遍历结果
  26. while(rs.next()){ System.out.println(rs.getInt("patientID")+"\t"+rs.getString("patientName")+"\t"+rs.getString("gender")+"\t"+rs.getString("address"));
  27. }
  28. } catch (SQLException e) {
  29. logger.error(e);
  30. } finally {
  31. try {
  32. if(null!=rs){
  33. rs.close();
  34. }
  35. if (null != stmt) {
  36. stmt.close();
  37. }
  38. if (null != conn) {
  39. conn.close();
  40. System.out.println("连接断开");
  41. }
  42. } catch (SQLException e) {
  43. logger.error(e);
  44. }
  45. }
  46. }
  1. public class HospitalInsert {
  2. private static Logger logger= LogManager.getLogger(HospitalInsert.class.getName()); public static void main(String[] args) {
  3. Connection conn=null; Statement stmt=null;
  4. String name="张菲";
  5. String gender="女";
  6. String birthDate="1995-02-12";
  7. String phoneNum="13887676500";
  8. String email="fei.zhang@qq.com";
  9. String passWord="909000";
  10. String identityNum="610000199502126100";
  11. String address="北京市";
  12. //1.加载驱动
  13. try {
  14. Class.forName("com.mysql.jdbc.Driver");
  15. } catch (ClassNotFoundException e) {
  16. logger.error(e);
  17. }
  18. //2.建立连接
  19. try {
  20. conn= DriverManager.getConnection("jdbc:mysql://localhost:3306/hospital?serverTimezone=GMT-8&useUnicode=true&characterEncoding=utf-8","cty","cty");
  21. //创建Statement对象
  22. stmt=conn.createStatement();
  23. //构造sql
  24. StringBuffer sbSql=new StringBuffer("insert into patient(password,birthDate,patientName,"+"phoneNum,email,identityNum,address)"+ "VALUES('");
  25. sbSql.append(passWord+"','");
  26. sbSql.append(birthDate+"','");
  27. sbSql.append(name+"','");
  28. sbSql.append(phoneNum+"','");
  29. sbSql.append(email+"','");
  30. sbSql.append(identityNum+"','");
  31. sbSql.append(address+"');");
  32. System.out.println(sbSql.toString());
  33. stmt.execute(sbSql.toString());
  34. } catch (SQLException e) {
  35. logger.error(e);
  36. }finally{
  37. try {
  38. if(null!=stmt){
  39. stmt.close();
  40. }
  41. if(null!=conn){
  42. conn.close();
  43. }
  44. } catch (SQLException e) {
  45. logger.error(e);
  46. }
  47. }
  48. }
  1. public class demo3 {
  2. public static void main(String[] args) {
  3. Scanner in=new Scanner(System.in);
  4. Connection con = null; PreparedStatement stmt=null; ResultSet rs=null;
  5. try {
  6. Class.forName("com.mysql.jdbc.Driver");
  7. con = DriverManager.getConnection("jdbc:mysql://localhost:3306/paycorp?serverTimezone=GMT-8&useUnicode=true&characterEncoding=utf-8", "cty", "cty");
  8. System.out.println("连接成功");
  9. String sql="select * from account where accountName=? and pwd=?"; System.out.println("请输入用户名:");
  10. String name=in.next();
  11. System.out.println("请输入密码:");
  12. String pwd=in.next();
  13. stmt=con.prepareStatement(sql);
  14. stmt.setString(1,name);
  15. stmt.setString(2,pwd);
  16. rs=stmt.executeQuery();
  17. if(rs.next()){
  18. System.out.println("成功");
  19. }else{ System.out.println("失败");
  20. }
  21. } catch (ClassNotFoundException e) {
  22. e.printStackTrace();
  23. } catch (SQLException throwables) {
  24. throwables.printStackTrace();
  25. }finally{
  26. try {
  27. if(null!=rs){
  28. rs.close();
  29. }
  30. if(null!=stmt){
  31. stmt.close();
  32. }
  33. if(null!=con){
  34. con.close();
  35. }
  36. } catch (SQLException throwables) {
  37. throwables.printStackTrace();
  38. }
  39. }
  40. }

&useUnicode=true&characterEncoding=utf-8”加上这段代码可以解决输入插入到数据库时乱码的问题
JDBC详细讲解链接:
https://blog.csdn.net/Jungle_Rao/article/details/81274720?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163762739316780264092527%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=163762739316780264092527&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-81274720.first_rank_v2_pc_rank_v29&utm_term=jdbc&spm=1018.2226.3001.4187

Statement和PreparedStatement的异同及优缺点

同:两者都是用来执SQL语句的
异:PreparedStatement需要根据SQL语句来创建,它能够通过设置参数,指定相应的值,不是像Statement那样使用字符串拼接的方式。

PreparedStatement的优点:

1、其使用参数设置,可读性好,不易记错。在statement中使用字符串拼接,可读性和维护性比较差。
2、其具有预编译机制,性能比statement更快。
3、其能够有效防止SQL注入攻击。

execute和executeUpdate的区别

相同点:二者都能够执行增加、删除、修改等操作。
不同点:
1、execute可以执行查询语句,然后通过getResult把结果取出来。executeUpdate不能执行查询语句。
2、execute返回Boolean类型,true表示执行的是查询语句,false表示执行的insert、delete、update等。executeUpdate的返回值是int,表示有多少条数据受到了影响。

//1.加载驱动
//2.建立连接
//3.创建执行对象
//4.开始执行SQL
//5.处理执行结果
//6.释放资源